xref: /lighttpd1.4/src/mod_mbedtls.c (revision 463c60ce)
1 /*
2  * mod_mbedtls - mbedTLS support for lighttpd
3  *
4  * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com  All rights reserved
5  * License: BSD 3-clause (same as lighttpd)
6  */
7 /*
8  * reference:
9  * https://tls.mbed.org/high-level-design
10  * https://tls.mbed.org/tech-updates/blog/mbedtls-2.0-defaults-best-practices
11  * mbedTLS header files (mbedtls/ssl.h and others) are extremely well-documented
12  * https://tls.mbed.org/api/  (generated from mbedTLS headers and code)
13  *
14  * mbedTLS limitations:
15  * - mbedTLS does not currently support OCSP
16  *   https://tls.mbed.org/discussions/feature-request/ocsp-stapling
17  *   TLS/DTLS: OCSP Stapling support #880
18  *   https://github.com/ARMmbed/mbedtls/issues/880
19  *   Add support for writing OCSP requests and parsing OCSP responses #1197
20  *   https://github.com/ARMmbed/mbedtls/issues/1197
21  *
22  * future possible enhancements to lighttpd mod_mbedtls:
23  * - session cache (though session tickets are implemented)
24  *     sample code in mbedtls:programs/ssl/ssl_server2.c
25  *     (and do not enable unless server.feature-flags ssl.session-cache enabled)
26  *
27  * Note: If session tickets are -not- disabled with
28  *     ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket")
29  *   mbedtls rotates the session ticket key according to 2x timeout set with
30  *   mbedtls_ssl_ticket_setup() (currently 43200 s, so 24 hour ticket lifetime)
31  *   This is fine for use with a single lighttpd instance, but with multiple
32  *   lighttpd workers, no coordinated STEK (server ticket encryption key)
33  *   rotation occurs unless ssl.stek-file is defined and maintained (preferred),
34  *   or if some external job restarts lighttpd.  Restarting lighttpd generates a
35  *   new key that is shared by lighttpd workers for the lifetime of the new key.
36  *   If the rotation period expires and lighttpd has not been restarted, and if
37  *   ssl.stek-file is not in use, then lighttpd workers will generate new
38  *   independent keys, making session tickets less effective for session
39  *   resumption, since clients have a lower chance for future connections to
40  *   reach the same lighttpd worker.  However, things will still work, and a new
41  *   session will be created if session resumption fails.  Admins should plan to
42  *   restart lighttpd at least every 12 hours if session tickets are enabled and
43  *   multiple lighttpd workers are configured.  Since that is likely disruptive,
44  *   if multiple lighttpd workers are configured, ssl.stek-file should be
45  *   defined and the file maintained externally.
46  */
47 #include "first.h"
48 
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <stdarg.h>
54 #include <stdlib.h>
55 #include <stdio.h>      /* vsnprintf() */
56 #include <string.h>
57 
58 #include <mbedtls/version.h>
59 /*(compatibility while waiting for future mbedtls 3.x interfaces)*/
60 #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.02.0 */
61 #ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS
62 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
63 #endif
64 #endif
65 #include <mbedtls/ctr_drbg.h>
66 #include <mbedtls/debug.h>
67 #include <mbedtls/dhm.h>
68 #include <mbedtls/error.h>
69 #include <mbedtls/entropy.h>
70 #include <mbedtls/oid.h>
71 #include <mbedtls/pem.h>
72 #include <mbedtls/ssl.h>
73 #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
74 #include <mbedtls/ssl_internal.h> /* struct mbedtls_ssl_transform */
75 #endif
76 #include <mbedtls/x509.h>
77 #include <mbedtls/x509_crt.h>
78 #include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
79 
80 #if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.04.0 */
81 #include <mbedtls/net_sockets.h>
82 #else
83 #include <mbedtls/net.h>
84 #endif
85 
86 #if defined(MBEDTLS_SSL_TICKET_C)
87 #include <mbedtls/ssl_ticket.h>
88 #endif
89 
90 #ifndef MBEDTLS_X509_CRT_PARSE_C
91 #error "lighttpd requires that mbedtls be built with MBEDTLS_X509_CRT_PARSE_C"
92 #endif
93 
94 #ifndef MBEDTLS_PRIVATE
95 #define MBEDTLS_PRIVATE(x) x
96 #endif
97 
98 #include "base.h"
99 #include "ck.h"
100 #include "fdevent.h"
101 #include "http_header.h"
102 #include "http_kv.h"
103 #include "log.h"
104 #include "plugin.h"
105 
106 typedef struct {
107     /* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */
108     mbedtls_pk_context ssl_pemfile_pkey;/* parsed private key structure */
109     mbedtls_x509_crt ssl_pemfile_x509;  /* parsed public key structure */
110     const buffer *ssl_pemfile;
111     const buffer *ssl_privkey;
112     int8_t need_chain;
113 } plugin_cert;
114 
115 typedef struct {
116     mbedtls_ssl_config *ssl_ctx;        /* context shared between mbedtls_ssl_CONTEXT structures */
117     int *ciphersuites;
118     void *curves;
119 } plugin_ssl_ctx;
120 
121 typedef struct {
122     mbedtls_ssl_config *ssl_ctx;        /* output from network_init_ssl() */
123     int *ciphersuites;                  /* output from network_init_ssl() */
124     void *curves;                       /* output from network_init_ssl() */
125 
126     /*(used only during startup; not patched)*/
127     unsigned char ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */
128     unsigned char ssl_honor_cipher_order; /* determine SSL cipher in server-preferred order, not client-order */
129     const buffer *ssl_cipher_list;
130     const buffer *ssl_acme_tls_1;
131     array *ssl_conf_cmd;
132 
133     /*(copied from plugin_data for socket ssl_ctx config)*/
134     plugin_cert *pc;
135     mbedtls_pk_context *ssl_pemfile_pkey; /* parsed private key structure */
136     mbedtls_x509_crt *ssl_pemfile_x509;   /* parsed public key structure */
137     mbedtls_x509_crt *ssl_ca_file;
138     const buffer *ssl_pemfile;
139     const buffer *ssl_privkey;
140     unsigned char ssl_session_ticket;
141     unsigned char ssl_verifyclient;
142     unsigned char ssl_verifyclient_enforce;
143     unsigned char ssl_verifyclient_depth;
144 } plugin_config_socket; /*(used at startup during configuration)*/
145 
146 typedef struct {
147     /* SNI per host: w/ COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */
148     plugin_cert *pc;
149     mbedtls_pk_context *ssl_pemfile_pkey; /* parsed private key structure */
150     mbedtls_x509_crt *ssl_pemfile_x509;   /* parsed public key structure */
151     const buffer *ssl_pemfile;
152     mbedtls_x509_crt *ssl_ca_file;
153     mbedtls_x509_crt *ssl_ca_dn_file;
154     mbedtls_x509_crl *ssl_ca_crl_file;
155 
156     unsigned char ssl_verifyclient;
157     unsigned char ssl_verifyclient_enforce;
158     unsigned char ssl_verifyclient_depth;
159     unsigned char ssl_verifyclient_export_cert;
160     unsigned char ssl_read_ahead;
161     unsigned char ssl_log_noise;
162     const buffer *ssl_verifyclient_username;
163     const buffer *ssl_acme_tls_1;
164 } plugin_config;
165 
166 typedef struct {
167     PLUGIN_DATA;
168     plugin_ssl_ctx *ssl_ctxs;
169     plugin_config defaults;
170     server *srv;
171     /* NIST counter-mode deterministic random byte generator */
172     mbedtls_ctr_drbg_context ctr_drbg;
173     /* entropy collection and state management */
174     mbedtls_entropy_context entropy;
175   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
176     mbedtls_ssl_ticket_context ticket_ctx;
177     const char *ssl_stek_file;
178   #endif
179 } plugin_data;
180 
181 static int ssl_is_init;
182 /* need assigned p->id for deep access of module handler_ctx for connection
183  *   i.e. handler_ctx *hctx = con->plugin_ctx[plugin_data_singleton->id]; */
184 static plugin_data *plugin_data_singleton;
185 #ifdef MBEDTLS_SSL_OUT_CONTENT_LEN
186 #define LOCAL_SEND_BUFSIZE MBEDTLS_SSL_OUT_CONTENT_LEN
187 #else
188 #define LOCAL_SEND_BUFSIZE MBEDTLS_SSL_MAX_CONTENT_LEN
189 #endif
190 static char *local_send_buffer;
191 
192 typedef struct {
193     mbedtls_ssl_context ssl;      /* mbedtls request/connection context */
194     request_st *r;
195     connection *con;
196     int8_t close_notify;
197     unsigned short alpn;
198     int handshake_done;
199     size_t pending_write;
200     plugin_config conf;
201     buffer *tmp_buf;
202     log_error_st *errh;
203     mbedtls_ssl_config *ssl_ctx;
204     mbedtls_pk_context *acme_tls_1_pkey;
205     mbedtls_x509_crt *acme_tls_1_x509;
206 } handler_ctx;
207 
208 
209 static handler_ctx *
210 handler_ctx_init (void)
211 {
212     handler_ctx *hctx = calloc(1, sizeof(*hctx));
213     force_assert(hctx);
214     return hctx;
215 }
216 
217 
218 static void
219 handler_ctx_free (handler_ctx *hctx)
220 {
221     mbedtls_ssl_free(&hctx->ssl);
222     if (hctx->acme_tls_1_pkey) {
223         mbedtls_pk_free(hctx->acme_tls_1_pkey);
224         free(hctx->acme_tls_1_pkey);
225     }
226     if (hctx->acme_tls_1_x509) {
227         mbedtls_x509_crt_free(hctx->acme_tls_1_x509);
228         free(hctx->acme_tls_1_x509);
229     }
230     free(hctx);
231 }
232 
233 
234 #ifdef MBEDTLS_ERROR_C
235 __attribute_cold__
236 static void elog(log_error_st * const errh,
237                  const char * const file, const int line,
238                  const int rc, const char * const msg)
239 {
240     /* error logging convenience function that decodes mbedtls result codes */
241     char buf[256];
242     mbedtls_strerror(rc, buf, sizeof(buf));
243     log_error(errh, file, line, "MTLS: %s: %s (-0x%04x)", msg, buf, -rc);
244 }
245 #else
246 #define elog(errh, file, line, rc, msg) \
247     log_error((errh), (file), (line), "MTLS: %s: (-0x%04x)", (msg), -(rc))
248 #endif
249 
250 
251 __attribute_cold__
252 __attribute_format__((__printf__, 5, 6))
253 static void elogf(log_error_st * const errh,
254                   const char * const file, const int line,
255                   const int rc, const char * const fmt, ...)
256 {
257     char msg[1024];
258     va_list ap;
259     va_start(ap, fmt);
260     vsnprintf(msg, sizeof(msg), fmt, ap);
261     va_end(ap);
262     elog(errh, file, line, rc, msg);
263 }
264 
265 
266 #ifdef MBEDTLS_SSL_SESSION_TICKETS
267 
268 #define TLSEXT_KEYNAME_LENGTH  16
269 #define TLSEXT_TICK_KEY_LENGTH 32
270 
271 /* construct our own session ticket encryption key structure
272  * to store keys that are not yet active
273  * (mirror from mod_openssl, even though not all bits are used here) */
274 typedef struct tlsext_ticket_key_st {
275     unix_time64_t active_ts; /* tickets not issued w/ key until activation ts*/
276     unix_time64_t expire_ts; /* key not valid after expiration timestamp */
277     unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH];
278     unsigned char tick_hmac_key[TLSEXT_TICK_KEY_LENGTH];
279     unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
280 } tlsext_ticket_key_t;
281 
282 static tlsext_ticket_key_t session_ticket_keys[1]; /* temp store until active */
283 static unix_time64_t stek_rotate_ts;
284 
285 
286 static int
287 mod_mbedtls_session_ticket_key_file (const char *fn)
288 {
289     /* session ticket encryption key (STEK)
290      *
291      * STEK file should be stored in non-persistent storage,
292      *   e.g. /dev/shm/lighttpd/stek-file  (in memory)
293      * with appropriate permissions set to keep stek-file from being
294      * read by other users.  Where possible, systems should also be
295      * configured without swap.
296      *
297      * admin should schedule an independent job to periodically
298      *   generate new STEK up to 3 times during key lifetime
299      *   (lighttpd stores up to 3 keys)
300      *
301      * format of binary file is:
302      *    4-byte - format version (always 0; for use if format changes)
303      *    4-byte - activation timestamp
304      *    4-byte - expiration timestamp
305      *   16-byte - session ticket key name
306      *   32-byte - session ticket HMAC encrpytion key
307      *   32-byte - session ticket AES encrpytion key
308      *
309      * STEK file can be created with a command such as:
310      *   dd if=/dev/random bs=1 count=80 status=none | \
311      *     perl -e 'print pack("iii",0,time()+300,time()+86400),<>' \
312      *     > STEK-file.$$ && mv STEK-file.$$ STEK-file
313      *
314      * The above delays activation time by 5 mins (+300 sec) to allow file to
315      * be propagated to other machines.  (admin must handle this independently)
316      * If STEK generation is performed immediately prior to starting lighttpd,
317      * admin should activate keys immediately (without +300).
318      */
319     int buf[23]; /* 92 bytes */
320     int rc = 0; /*(will retry on next check interval upon any error)*/
321     if (0 != fdevent_load_file_bytes((char *)buf,(off_t)sizeof(buf),0,fn,NULL))
322         return rc;
323     if (buf[0] == 0) { /*(format version 0)*/
324         session_ticket_keys[0].active_ts = TIME64_CAST(buf[1]);
325         session_ticket_keys[0].expire_ts = TIME64_CAST(buf[2]);
326       #ifndef __COVERITY__
327         memcpy(&session_ticket_keys[0].tick_key_name, buf+3, 80);
328       #else
329         memcpy(&session_ticket_keys[0].tick_key_name,
330                buf+3, TLSEXT_KEYNAME_LENGTH);
331         memcpy(&session_ticket_keys[0].tick_hmac_key,
332                buf+7, TLSEXT_TICK_KEY_LENGTH);
333         memcpy(&session_ticket_keys[0].tick_aes_key,
334                buf+15, TLSEXT_TICK_KEY_LENGTH);
335       #endif
336         rc = 1;
337     }
338 
339     mbedtls_platform_zeroize(buf, sizeof(buf));
340     return rc;
341 }
342 
343 
344 static void
345 mod_mbedtls_session_ticket_key_check (plugin_data *p, const unix_time64_t cur_ts)
346 {
347     if (NULL == p->ssl_stek_file) return;
348 
349     struct stat st;
350     if (0 == stat(p->ssl_stek_file, &st)
351         && TIME64_CAST(st.st_mtime) > stek_rotate_ts
352         && mod_mbedtls_session_ticket_key_file(p->ssl_stek_file)) {
353         stek_rotate_ts = cur_ts;
354     }
355 
356     tlsext_ticket_key_t *stek = session_ticket_keys;
357     if (stek->active_ts != 0 && stek->active_ts - 63 <= cur_ts) {
358       #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
359         int rc = mbedtls_ssl_ticket_rotate(&p->ticket_ctx,
360                    stek->tick_key_name, sizeof(stek->tick_key_name),
361                    stek->tick_aes_key, sizeof(stek->tick_aes_key),
362                    (uint32_t)(stek->expire_ts - stek->active_ts));
363         if (0 != rc)
364             elog(p->srv->errh, __FILE__,__LINE__, rc,
365                  "session ticket encryption key rotation failed");
366       #else /*(mbedtls_allow_private_access at top of file for [3.0.0,3.2.0))*/
367         /* expect to get newer ssl.stek-file prior to mbedtls detecting
368          * expiration and internally generating a new key.  If not, then
369          * lifetime may be up to 2x specified lifetime until overwritten
370          * by mbedtls, but original key will be overwritten and discarded */
371         mbedtls_ssl_ticket_context *ctx = &p->ticket_ctx;
372         ctx->ticket_lifetime = stek->expire_ts - stek->active_ts;
373         ctx->active = 1 - ctx->active;
374         mbedtls_ssl_ticket_key *key = ctx->keys + ctx->active;
375         /* set generation_time to cur_ts instead of stek->active_ts
376          * since ctx->active was updated */
377         key->generation_time = (uint32_t)cur_ts;
378         memcpy(key->name, stek->tick_key_name, sizeof(key->name));
379         /* With GCM and CCM, same context can encrypt & decrypt */
380         int rc = mbedtls_cipher_setkey(&key->ctx, stek->tick_aes_key,
381                                        mbedtls_cipher_get_key_bitlen(&key->ctx),
382                                        MBEDTLS_ENCRYPT);
383         if (0 != rc) { /* expire key immediately if error occurs */
384             key->generation_time = cur_ts > (unix_time64_t)ctx->ticket_lifetime
385               ? cur_ts - ctx->ticket_lifetime - 1
386               : 0;
387             ctx->active = 1 - ctx->active;
388         }
389       #endif
390         mbedtls_platform_zeroize(stek, sizeof(tlsext_ticket_key_t));
391     }
392 }
393 
394 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
395 
396 
397 INIT_FUNC(mod_mbedtls_init)
398 {
399     plugin_data_singleton = (plugin_data *)calloc(1, sizeof(plugin_data));
400   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
401     mbedtls_ssl_ticket_init(&plugin_data_singleton->ticket_ctx);
402   #endif
403     return plugin_data_singleton;
404 }
405 
406 
407 static int mod_mbedtls_init_once_mbedtls (server *srv)
408 {
409     if (ssl_is_init) return 1;
410     ssl_is_init = 1;
411 
412     plugin_data * const p = plugin_data_singleton;
413     mbedtls_ctr_drbg_init(&p->ctr_drbg); /* init empty NSIT random num gen */
414     mbedtls_entropy_init(&p->entropy);   /* init empty entropy collection struct
415                                                .. could add sources here too */
416 
417     int rc =                                      /* init RNG */
418       mbedtls_ctr_drbg_seed(&p->ctr_drbg,         /* random number generator */
419                             mbedtls_entropy_func, /* default entropy func */
420                             &p->entropy,          /* entropy context */
421                             NULL, 0);             /* no personalization data */
422     if (0 != rc) {
423         elog(srv->errh, __FILE__,__LINE__, rc,
424              "Init of random number generator failed");
425         return 0;
426     }
427 
428     local_send_buffer = malloc(LOCAL_SEND_BUFSIZE);
429     force_assert(NULL != local_send_buffer);
430 
431     return 1;
432 }
433 
434 
435 static void mod_mbedtls_free_mbedtls (void)
436 {
437     if (!ssl_is_init) return;
438 
439   #ifdef MBEDTLS_SSL_SESSION_TICKETS
440     mbedtls_platform_zeroize(session_ticket_keys, sizeof(session_ticket_keys));
441     stek_rotate_ts = 0;
442   #endif
443 
444     plugin_data * const p = plugin_data_singleton;
445     mbedtls_ctr_drbg_free(&p->ctr_drbg);
446     mbedtls_entropy_free(&p->entropy);
447   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
448     mbedtls_ssl_ticket_free(&p->ticket_ctx);
449   #endif
450 
451     free(local_send_buffer);
452     ssl_is_init = 0;
453 }
454 
455 
456 static void
457 mod_mbedtls_free_config (server *srv, plugin_data * const p)
458 {
459     if (NULL != p->ssl_ctxs) {
460         mbedtls_ssl_config * const ssl_ctx_global_scope = p->ssl_ctxs->ssl_ctx;
461         /* free ssl_ctx from $SERVER["socket"] (if not copy of global scope) */
462         for (uint32_t i = 1; i < srv->config_context->used; ++i) {
463             plugin_ssl_ctx * const s = p->ssl_ctxs + i;
464             if (s->ssl_ctx && s->ssl_ctx != ssl_ctx_global_scope) {
465                 mbedtls_ssl_config_free(s->ssl_ctx);
466                 free(s->ciphersuites);
467                 free(s->curves);
468             }
469         }
470         /* free ssl_ctx from global scope */
471         if (ssl_ctx_global_scope) {
472             mbedtls_ssl_config_free(ssl_ctx_global_scope);
473             free(p->ssl_ctxs[0].ciphersuites);
474             free(p->ssl_ctxs[0].curves);
475         }
476         free(p->ssl_ctxs);
477     }
478 
479     if (NULL == p->cvlist) return;
480     /* (init i to 0 if global context; to 1 to skip empty global context) */
481     for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) {
482         config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
483         for (; -1 != cpv->k_id; ++cpv) {
484             switch (cpv->k_id) {
485               case 0: /* ssl.pemfile */
486                 if (cpv->vtype == T_CONFIG_LOCAL) {
487                     plugin_cert *pc = cpv->v.v;
488                     mbedtls_pk_free(&pc->ssl_pemfile_pkey);
489                     mbedtls_x509_crt_free(&pc->ssl_pemfile_x509);
490                     free(pc);
491                 }
492                 break;
493               case 2: /* ssl.ca-file */
494               case 3: /* ssl.ca-dn-file */
495                 if (cpv->vtype == T_CONFIG_LOCAL) {
496                     mbedtls_x509_crt *cacert = cpv->v.v;
497                     mbedtls_x509_crt_free(cacert);
498                     free(cacert);
499                 }
500                 break;
501               case 4: /* ssl.ca-crl-file */
502                 if (cpv->vtype == T_CONFIG_LOCAL) {
503                     mbedtls_x509_crl *crl = cpv->v.v;
504                     mbedtls_x509_crl_free(crl);
505                     free(crl);
506                 }
507                 break;
508               default:
509                 break;
510             }
511         }
512     }
513 }
514 
515 
516 FREE_FUNC(mod_mbedtls_free)
517 {
518     plugin_data *p = p_d;
519     if (NULL == p->srv) return;
520     mod_mbedtls_free_config(p->srv, p);
521     mod_mbedtls_free_mbedtls();
522 }
523 
524 
525 static void
526 mod_mbedtls_merge_config_cpv (plugin_config * const pconf, const config_plugin_value_t * const cpv)
527 {
528     switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
529       case 0: /* ssl.pemfile */
530         if (cpv->vtype == T_CONFIG_LOCAL)
531             pconf->pc = cpv->v.v;
532         break;
533       case 1: /* ssl.privkey */
534         break;
535       case 2: /* ssl.ca-file */
536         if (cpv->vtype == T_CONFIG_LOCAL)
537             pconf->ssl_ca_file = cpv->v.v;
538         break;
539       case 3: /* ssl.ca-dn-file */
540         if (cpv->vtype == T_CONFIG_LOCAL)
541             pconf->ssl_ca_dn_file = cpv->v.v;
542         break;
543       case 4: /* ssl.ca-crl-file */
544         if (cpv->vtype == T_CONFIG_LOCAL)
545             pconf->ssl_ca_dn_file = cpv->v.v;
546         break;
547       case 5: /* ssl.read-ahead */
548         pconf->ssl_read_ahead = (0 != cpv->v.u);
549         break;
550       case 6: /* ssl.disable-client-renegotiation */
551         /*(ignored; unsafe renegotiation disabled by default)*/
552         break;
553       case 7: /* ssl.verifyclient.activate */
554         pconf->ssl_verifyclient = (0 != cpv->v.u);
555         break;
556       case 8: /* ssl.verifyclient.enforce */
557         pconf->ssl_verifyclient_enforce = (0 != cpv->v.u);
558         break;
559       case 9: /* ssl.verifyclient.depth */
560         pconf->ssl_verifyclient_depth = (unsigned char)cpv->v.shrt;
561         break;
562       case 10:/* ssl.verifyclient.username */
563         pconf->ssl_verifyclient_username = cpv->v.b;
564         break;
565       case 11:/* ssl.verifyclient.exportcert */
566         pconf->ssl_verifyclient_export_cert = (0 != cpv->v.u);
567         break;
568       case 12:/* ssl.acme-tls-1 */
569         pconf->ssl_acme_tls_1 = cpv->v.b;
570         break;
571       case 13:/* debug.log-ssl-noise */
572         pconf->ssl_log_noise = (unsigned char)cpv->v.shrt;
573         break;
574      #if 0    /*(cpk->k_id remapped in mod_mbedtls_set_defaults())*/
575       case 14:/* ssl.verifyclient.ca-file */
576       case 15:/* ssl.verifyclient.ca-dn-file */
577       case 16:/* ssl.verifyclient.ca-crl-file */
578         break;
579      #endif
580       default:/* should not happen */
581         return;
582     }
583 }
584 
585 
586 static void
587 mod_mbedtls_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv)
588 {
589     do {
590         mod_mbedtls_merge_config_cpv(pconf, cpv);
591     } while ((++cpv)->k_id != -1);
592 }
593 
594 
595 static void
596 mod_mbedtls_patch_config (request_st * const r, plugin_config * const pconf)
597 {
598     plugin_data * const p = plugin_data_singleton;
599     memcpy(pconf, &p->defaults, sizeof(plugin_config));
600     for (int i = 1, used = p->nconfig; i < used; ++i) {
601         if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id))
602             mod_mbedtls_merge_config(pconf, p->cvlist + p->cvlist[i].v.u2[0]);
603     }
604 }
605 
606 
607 __attribute_pure__
608 static int
609 mod_mbedtls_crt_is_self_issued (const mbedtls_x509_crt * const crt)
610 {
611     const mbedtls_x509_buf * const issuer  = &crt->issuer_raw;
612     const mbedtls_x509_buf * const subject = &crt->subject_raw;
613     return subject->len == issuer->len
614         && 0 == memcmp(issuer->p, subject->p, subject->len);
615 }
616 
617 
618 static int
619 mod_mbedtls_construct_crt_chain (mbedtls_x509_crt *leaf, mbedtls_x509_crt *store, log_error_st *errh)
620 {
621     /* Historically, openssl will use the cert chain in (SSL_CTX *) if a cert
622      * does not have a chain configured in (SSL *).  While similar behavior
623      * could be achieved with mbedtls_x509_crt_parse_file(crt, ssl_ca_file->ptr)
624      * instead attempt to do better and build a proper, ordered cert chain. */
625 
626     if (leaf->next) return 0; /*(presume chain has already been provided)*/
627     if (store == NULL) return 0;/*(unable to proceed; chain may be incomplete)*/
628 
629     /* attempt to construct certificate chain from certificate store */
630     for (mbedtls_x509_crt *crt = leaf; crt; ) {
631         const mbedtls_x509_buf * const issuer = &crt->issuer_raw;
632 
633         /*(walk entire store in case certs are not properly sorted)*/
634         for (crt = store; crt; crt = crt->next) {
635             /* The raw issuer/subject data (DER) is used for quick comparison */
636             /* (see comments in mod_mbedtls_verify_cb())*/
637             const mbedtls_x509_buf * const subject = &crt->subject_raw;
638             if (issuer->len != subject->len
639                 || 0 != memcmp(subject->p, issuer->p, issuer->len)) continue;
640 
641             /* root cert is end condition; omit from chain of intermediates */
642             if (mod_mbedtls_crt_is_self_issued(crt))
643                 return 0;
644 
645             int rc =
646           #if MBEDTLS_VERSION_NUMBER >= 0x02110000 /* mbedtls 2.17.0 */
647               /* save memory by eliding copy of already-loaded raw DER */
648               mbedtls_x509_crt_parse_der_nocopy(leaf, crt->raw.p, crt->raw.len);
649           #else
650               mbedtls_x509_crt_parse_der(leaf, crt->raw.p, crt->raw.len);
651           #endif
652             if (0 != rc) { /*(failure not unexpected since already parsed)*/
653                 elog(errh, __FILE__, __LINE__, rc, "cert copy failed");
654                 return rc;
655             }
656             break;
657         }
658     }
659 
660     return 0; /*(no error, though cert chain may or may not be complete)*/
661 }
662 
663 
664 static int
665 mod_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
666 {
667     handler_ctx * const hctx = (handler_ctx *)arg;
668 
669     if (depth > hctx->conf.ssl_verifyclient_depth) {
670         log_error(hctx->r->conf.errh, __FILE__, __LINE__,
671                   "MTLS: client cert chain too long");
672         *flags |= MBEDTLS_X509_BADCERT_OTHER; /* cert chain too long */
673     }
674     else if (0 == depth && NULL != hctx->conf.ssl_ca_dn_file) {
675         /* verify that client cert is issued by CA in ssl.ca-dn-file
676          * if both ssl.ca-dn-file and ssl.ca-file were configured */
677         /* The raw issuer/subject data (DER) is used for quick comparison. */
678         const size_t len = crt->issuer_raw.len;
679         mbedtls_x509_crt *chain = hctx->conf.ssl_ca_dn_file;
680         do {
681           #if 0 /* x509_name_cmp() is not a public func in mbedtls */
682             if (0 == x509_name_cmp(&crt->issuer, &chain->subject))
683                 break;
684           #else
685             if (len == chain->subject_raw.len
686                 && 0 == memcmp(chain->subject_raw.p, crt->issuer_raw.p, len))
687                 break;
688           #endif
689         } while ((chain = chain->next));
690 
691         if (NULL == chain)
692             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
693     }
694     if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
695         log_error(hctx->r->conf.errh, __FILE__, __LINE__,
696                   "MTLS: client cert not trusted");
697     }
698 
699     return 0;
700 }
701 
702 
703 enum {
704   MOD_MBEDTLS_ALPN_HTTP11      = 1
705  ,MOD_MBEDTLS_ALPN_HTTP10      = 2
706  ,MOD_MBEDTLS_ALPN_H2          = 3
707  ,MOD_MBEDTLS_ALPN_ACME_TLS_1  = 4
708 };
709 
710 #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
711 #ifdef MBEDTLS_SSL_ALPN
712 
713 static int
714 mod_mbedtls_acme_tls_1 (handler_ctx *hctx);
715 
716 #endif
717 #endif
718 
719 
720 #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
721 #define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO
722 #define MBEDTLS_ERR_SSL_DECODE_ERROR      MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO
723 #endif
724 
725 
726 #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
727 static int
728 mod_mbedtls_SNI (void *arg, mbedtls_ssl_context *ssl, const unsigned char *servername, size_t len)
729 {
730     handler_ctx * const hctx = (handler_ctx *) arg;
731     request_st * const r = hctx->r;
732     buffer_copy_string_len(&r->uri.scheme, CONST_STR_LEN("https"));
733 
734     if (len >= 1024) { /*(expecting < 256; TLSEXT_MAXLEN_host_name is 255)*/
735         log_error(r->conf.errh, __FILE__, __LINE__,
736                   "MTLS: SNI name too long %.*s", (int)len, servername);
737         return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
738     }
739 
740     /* use SNI to patch mod_mbedtls config and then reset COMP_HTTP_HOST */
741     buffer_copy_string_len_lc(&r->uri.authority, (const char *)servername, len);
742   #if 0
743     /*(r->uri.authority used below for configuration before request read;
744      * revisit for h2)*/
745     if (0 != http_request_host_policy(&r->uri.authority,
746                                       r->conf.http_parseopts, 443))
747         return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
748   #endif
749 
750     const buffer * const ssl_pemfile = hctx->conf.pc->ssl_pemfile;
751 
752     r->conditional_is_valid |= (1 << COMP_HTTP_SCHEME)
753                             |  (1 << COMP_HTTP_HOST);
754 
755     mod_mbedtls_patch_config(r, &hctx->conf);
756     /* reset COMP_HTTP_HOST so that conditions re-run after request hdrs read */
757     /*(done in configfile-glue.c:config_cond_cache_reset() after request hdrs read)*/
758     /*config_cond_cache_reset_item(r, COMP_HTTP_HOST);*/
759     /*buffer_clear(&r->uri.authority);*/
760 
761   #ifdef MBEDTLS_SSL_ALPN
762     /* TLS-ALPN-01 (ALPN "acme-tls/1") requires SNI */
763     if (hctx->alpn == MOD_MBEDTLS_ALPN_ACME_TLS_1)
764         return mod_mbedtls_acme_tls_1(hctx);
765   #endif
766 
767     /*(compare strings as ssl.pemfile might repeat same file in lighttpd.conf
768      * and mod_mbedtls does not attempt to de-dup)*/
769     if (!buffer_is_equal(hctx->conf.pc->ssl_pemfile, ssl_pemfile)) {
770         /* if needed, attempt to construct certificate chain for server cert */
771         if (hctx->conf.pc->need_chain) {
772             hctx->conf.pc->need_chain = 0; /*(attempt once to complete chain)*/
773             mbedtls_x509_crt *ssl_cred = &hctx->conf.pc->ssl_pemfile_x509;
774             mbedtls_x509_crt *store = hctx->conf.ssl_ca_file;
775             if (0 != mod_mbedtls_construct_crt_chain(ssl_cred, store,
776                                                      r->conf.errh))
777                 return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
778         }
779         /* reconfigure to use SNI-specific cert */
780         int rc =
781           mbedtls_ssl_set_hs_own_cert(ssl,
782                                       &hctx->conf.pc->ssl_pemfile_x509,
783                                       &hctx->conf.pc->ssl_pemfile_pkey);
784         if (0 != rc) {
785             elogf(r->conf.errh, __FILE__, __LINE__, rc,
786                   "failed to set SNI certificate for TLS server name %s",
787                   r->uri.authority.ptr);
788             return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
789         }
790     }
791 
792     return 0;
793 }
794 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
795 
796 
797 static int
798 mod_mbedtls_conf_verify (handler_ctx *hctx)
799 {
800     if (NULL == hctx->conf.ssl_ca_file) {
801         log_error(hctx->r->conf.errh, __FILE__, __LINE__,
802           "MTLS: can't verify client without ssl.verifyclient.ca-file "
803           "for TLS server name %s",
804           hctx->r->uri.authority.ptr);
805         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
806     }
807 
808     mbedtls_ssl_context * const ssl = &hctx->ssl;
809 
810   #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
811     int mode = (hctx->conf.ssl_verifyclient_enforce)
812       ? MBEDTLS_SSL_VERIFY_REQUIRED
813       : MBEDTLS_SSL_VERIFY_OPTIONAL;
814     mbedtls_ssl_set_hs_authmode(ssl, mode);
815     mbedtls_ssl_set_hs_ca_chain(ssl, hctx->conf.ssl_ca_file,
816                                      hctx->conf.ssl_ca_crl_file);
817     if (hctx->conf.ssl_ca_dn_file)
818         mbedtls_ssl_set_hs_dn_hints(ssl, hctx->conf.ssl_ca_dn_file);
819   #else
820     /* send ssl_ca_dn_file (if set) in client certificate request
821      * (later changed to ssl_ca_file before client certificate verification) */
822     mbedtls_x509_crt *ca_certs = hctx->conf.ssl_ca_dn_file
823                                ? hctx->conf.ssl_ca_dn_file
824                                : hctx->conf.ssl_ca_file;
825     mbedtls_ssl_set_hs_ca_chain(ssl, ca_certs, hctx->conf.ssl_ca_crl_file);
826   #endif
827   #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
828     mbedtls_ssl_set_verify(ssl, mod_mbedtls_verify_cb, hctx);
829   #else
830     /* overwrite callback with hctx each time we enter here, before handshake
831      * (Some callbacks are on mbedtls_ssl_config, not mbedtls_ssl_context)
832      * (Not thread-safe if config (mbedtls_ssl_config *ssl_ctx) is shared)
833      * (XXX: there is probably a better way to do this...) */
834     mbedtls_ssl_conf_verify(hctx->ssl_ctx, mod_mbedtls_verify_cb, hctx);
835   #endif
836     return 0;
837 }
838 
839 
840 /* mbedTLS interfaces are generally excellent.  mbedTLS convenience interfaces
841  * to read CRLs, X509 certs, and private keys are uniformly paranoid about
842  * clearing memory.  At the moment, stdio routines fopen(), fread(), fclose()
843  * are used for portability, but without setvbuf(stream, NULL, _IOLBF, 0),
844  * again for portability, since setvbuf() is not necessarily available.  Since
845  * stdio buffers by default, use our own funcs to read files without buffering.
846  * mbedtls_pk_load_file() includes trailing '\0' in size when contents in PEM
847  * format, so do the same with the value returned from fdevent_load_file().
848  */
849 
850 
851 static int
852 mod_mbedtls_x509_crl_parse_file (mbedtls_x509_crl *chain, const char *fn)
853 {
854     int rc = MBEDTLS_ERR_X509_FILE_IO_ERROR;
855     off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
856     char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
857     if (NULL == data) return rc;
858 
859     rc = mbedtls_x509_crl_parse(chain, (unsigned char *)data, (size_t)dlen+1);
860 
861     if (dlen) ck_memzero(data, (size_t)dlen);
862     free(data);
863 
864     return rc;
865 }
866 
867 
868 static int
869 mod_mbedtls_cert_is_active (const mbedtls_x509_crt *crt)
870 {
871     return (   !mbedtls_x509_time_is_future(&crt->valid_from)
872             && !mbedtls_x509_time_is_past(&crt->valid_to));
873 }
874 
875 
876 #if MBEDTLS_VERSION_NUMBER >= 0x02170000 /* mbedtls 2.23.0 */
877 
878 static int
879 mod_mbedtls_x509_crt_ext_cb (void *p_ctx,
880                              mbedtls_x509_crt const *crt,
881                              mbedtls_x509_buf const *oid,
882                              int critical,
883                              const unsigned char *p,
884                              const unsigned char *end)
885 {
886     UNUSED(p_ctx);
887     if (!mod_mbedtls_cert_is_active(crt))
888         return MBEDTLS_ERR_X509_INVALID_DATE;
889     /* id-pe-acmeIdentifier 1.3.6.1.5.5.7.1.31 */
890     static const unsigned char acmeIdentifier[] = MBEDTLS_OID_PKIX "\x01\x1f";
891     if (0 == MBEDTLS_OID_CMP(acmeIdentifier, oid)) {
892         if (!critical) /* required by RFC 8737 */
893             return MBEDTLS_ERR_X509_INVALID_EXTENSIONS
894                  + MBEDTLS_ERR_ASN1_INVALID_DATA;
895         /*(mbedtls_asn1_get_tag() should take first param as
896          * (const unsigned char **) so safe to cast away const)*/
897         unsigned char *q;
898         *(const unsigned char **)&q = p;
899         size_t len;
900         int rc = mbedtls_asn1_get_tag(&q, end, &len,
901                                       MBEDTLS_ASN1_OCTET_STRING
902                                      |MBEDTLS_ASN1_PRIMITIVE);
903         if (0 != rc)
904             return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + rc;
905         if (q + len != end)
906             return MBEDTLS_ERR_X509_INVALID_EXTENSIONS
907                  + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
908         if (len != 32) /* must be OCTET STRING (SIZE (32)) */
909             return MBEDTLS_ERR_X509_INVALID_EXTENSIONS
910                  + MBEDTLS_ERR_ASN1_INVALID_LENGTH;
911         return 0;
912     }
913     return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
914 }
915 
916 static int
917 mod_mbedtls_x509_crt_parse_acme (mbedtls_x509_crt *chain, const char *fn)
918 {
919     /* similar to mod_mbedtls_x509_crt_parse_file(), but read single cert
920      * and special case to handle id-pe-acmeIdentifier OID */
921     /* https://github.com/ARMmbed/mbedtls/issues/3241 */
922     int rc = MBEDTLS_ERR_X509_FILE_IO_ERROR;
923     off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
924     char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
925     if (NULL == data) return rc;
926 
927     mbedtls_pem_context pem;
928     mbedtls_pem_init(&pem);
929 
930     size_t use_len;
931     rc = mbedtls_pem_read_buffer(&pem,
932                                  "-----BEGIN CERTIFICATE-----",
933                                  "-----END CERTIFICATE-----",
934                                  (unsigned char *)data, NULL, 0, &use_len);
935     if (0 == rc) {
936         mbedtls_x509_crt_ext_cb_t cb = mod_mbedtls_x509_crt_ext_cb;
937       #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
938         size_t buflen;
939         const unsigned char *buf = mbedtls_pem_get_buffer(&pem, &buflen);
940       #else
941         const unsigned char *buf = pem.MBEDTLS_PRIVATE(buf);
942         size_t buflen = pem.MBEDTLS_PRIVATE(buflen);
943       #endif
944         rc = mbedtls_x509_crt_parse_der_with_ext_cb(chain,buf,buflen,1,cb,NULL);
945     }
946 
947     mbedtls_pem_free(&pem);
948 
949     if (dlen) ck_memzero(data, (size_t)dlen);
950     free(data);
951 
952     return rc;
953 }
954 
955 #endif
956 
957 
958 static int
959 mod_mbedtls_x509_crt_parse_file (mbedtls_x509_crt *chain, const char *fn)
960 {
961     int rc = MBEDTLS_ERR_X509_FILE_IO_ERROR;
962     off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
963     char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
964     if (NULL == data) return rc;
965 
966     rc = mbedtls_x509_crt_parse(chain, (unsigned char *)data, (size_t)dlen+1);
967 
968     if (dlen) ck_memzero(data, (size_t)dlen);
969     free(data);
970 
971     return rc;
972 }
973 
974 
975 static int
976 mod_mbedtls_pk_parse_keyfile (mbedtls_pk_context *ctx, const char *fn, const char *pwd)
977 {
978     int rc = MBEDTLS_ERR_PK_FILE_IO_ERROR;
979     off_t dlen = 512*1024*1024;/*(arbitrary limit: 512 MB file; expect < 1 MB)*/
980     char *data = fdevent_load_file(fn, &dlen, NULL, malloc, free);
981     if (NULL == data) return rc;
982 
983   #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
984     plugin_data * const p = plugin_data_singleton;
985     rc = mbedtls_pk_parse_key(ctx, (unsigned char *)data, (size_t)dlen+1,
986                               (const unsigned char *)pwd,
987                               pwd ? strlen(pwd) : 0,
988                               mbedtls_ctr_drbg_random, &p->ctr_drbg);
989   #else
990     rc = mbedtls_pk_parse_key(ctx, (unsigned char *)data, (size_t)dlen+1,
991                               (const unsigned char *)pwd,
992                               pwd ? strlen(pwd) : 0);
993   #endif
994 
995     if (dlen) ck_memzero(data, (size_t)dlen);
996     free(data);
997 
998     return rc;
999 }
1000 
1001 
1002 static void *
1003 network_mbedtls_load_pemfile (server *srv, const buffer *pemfile, const buffer *privkey)
1004 {
1005     mbedtls_x509_crt ssl_pemfile_x509;   /* parsed public key structure */
1006     mbedtls_pk_context ssl_pemfile_pkey; /* parsed private key structure */
1007     int rc;
1008 
1009     mbedtls_x509_crt_init(&ssl_pemfile_x509); /* init cert structure */
1010     rc = mod_mbedtls_x509_crt_parse_file(&ssl_pemfile_x509, pemfile->ptr);
1011     if (0 != rc) {
1012         elogf(srv->errh, __FILE__, __LINE__, rc,
1013               "PEM file cert read failed (%s)", pemfile->ptr);
1014         return NULL;
1015     }
1016     else if (!mod_mbedtls_cert_is_active(&ssl_pemfile_x509)) {
1017         log_error(srv->errh, __FILE__, __LINE__,
1018           "MTLS: inactive/expired X509 certificate '%s'", pemfile->ptr);
1019     }
1020 
1021     mbedtls_pk_init(&ssl_pemfile_pkey);  /* init private key context */
1022     rc = mod_mbedtls_pk_parse_keyfile(&ssl_pemfile_pkey, privkey->ptr, NULL);
1023     if (0 != rc) {
1024         elogf(srv->errh, __FILE__, __LINE__, rc,
1025               "PEM file private key read failed %s", privkey->ptr);
1026         mbedtls_x509_crt_free(&ssl_pemfile_x509);
1027         return NULL;
1028     }
1029 
1030   #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
1031     plugin_data * const p = plugin_data_singleton;
1032     rc = mbedtls_pk_check_pair(&ssl_pemfile_x509.pk, &ssl_pemfile_pkey,
1033                                mbedtls_ctr_drbg_random, &p->ctr_drbg);
1034   #else
1035     rc = mbedtls_pk_check_pair(&ssl_pemfile_x509.pk, &ssl_pemfile_pkey);
1036   #endif
1037     if (0 != rc) {
1038         elogf(srv->errh, __FILE__, __LINE__, rc,
1039               "PEM cert and private key did not verify (%s) (%s)",
1040               pemfile->ptr, privkey->ptr);
1041         mbedtls_pk_free(&ssl_pemfile_pkey);
1042         mbedtls_x509_crt_free(&ssl_pemfile_x509);
1043         return NULL;
1044     }
1045 
1046     plugin_cert *pc = malloc(sizeof(plugin_cert));
1047     force_assert(pc);
1048     pc->ssl_pemfile_pkey = ssl_pemfile_pkey;
1049     pc->ssl_pemfile_x509 = ssl_pemfile_x509;
1050     pc->ssl_pemfile = pemfile;
1051     pc->ssl_privkey = privkey;
1052     pc->need_chain = (ssl_pemfile_x509.next == NULL
1053                       && !mod_mbedtls_crt_is_self_issued(&ssl_pemfile_x509));
1054     mbedtls_platform_zeroize(&ssl_pemfile_pkey, sizeof(ssl_pemfile_pkey));
1055 
1056   #if 0
1057     /* needed at top of file for portable timegm(): #include "sys-time.h" */
1058     struct tm tm;
1059     memset(&tm, 0, sizeof(tm));
1060     mbedtls_x509_time *notAfter = &ssl_pemfile_x509->valid_to;
1061     tm.tm_sec   = notAfter->sec;
1062     tm.tm_min   = notAfter->min;
1063     tm.tm_hour  = notAfter->hour;
1064     tm.tm_mday  = notAfter->day;
1065     tm.tm_mon   = notAfter->mon;
1066     tm.tm_year  = notAfter->year;
1067     pc->notAfter = TIME64_CAST(timegm(&tm));
1068   #endif
1069 
1070     return pc;
1071 }
1072 
1073 
1074 #ifdef MBEDTLS_SSL_ALPN
1075 
1076 #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
1077 static int
1078 mod_mbedtls_acme_tls_1 (handler_ctx *hctx)
1079 {
1080     buffer * const b = hctx->tmp_buf;
1081     const buffer * const name = &hctx->r->uri.authority;
1082     log_error_st * const errh = hctx->r->conf.errh;
1083     mbedtls_x509_crt *ssl_pemfile_x509 = NULL;
1084     mbedtls_pk_context *ssl_pemfile_pkey = NULL;
1085     size_t len;
1086     int rc = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
1087 
1088     /* check if acme-tls/1 protocol is enabled (path to dir of cert(s) is set)*/
1089     if (!hctx->conf.ssl_acme_tls_1)
1090         return 0; /*(should not happen)*/
1091 
1092     /* check if SNI set server name (required for acme-tls/1 protocol)
1093      * and perform simple path checks for no '/'
1094      * and no leading '.' (e.g. ignore "." or ".." or anything beginning '.') */
1095     if (buffer_is_blank(name))          return rc;
1096     if (NULL != strchr(name->ptr, '/')) return rc;
1097     if (name->ptr[0] == '.')            return rc;
1098   #if 0
1099     if (0 != http_request_host_policy(name,hctx->r->conf.http_parseopts,443))
1100         return rc;
1101   #endif
1102     buffer_copy_path_len2(b, BUF_PTR_LEN(hctx->conf.ssl_acme_tls_1),
1103                              BUF_PTR_LEN(name));
1104     len = buffer_clen(b);
1105 
1106     do {
1107         buffer_append_string_len(b, CONST_STR_LEN(".crt.pem"));
1108         ssl_pemfile_x509 = malloc(sizeof(*ssl_pemfile_x509));
1109         force_assert(ssl_pemfile_x509);
1110         mbedtls_x509_crt_init(ssl_pemfile_x509); /* init cert structure */
1111       #if MBEDTLS_VERSION_NUMBER >= 0x02170000 /* mbedtls 2.23.0 */
1112         rc = mod_mbedtls_x509_crt_parse_acme(ssl_pemfile_x509, b->ptr);
1113       #else /*(will fail; unable to handle id-pe-acmeIdentifier OID)*/
1114         rc = mod_mbedtls_x509_crt_parse_file(ssl_pemfile_x509, b->ptr);
1115       #endif
1116         if (0 != rc) {
1117             elogf(errh, __FILE__, __LINE__, rc,
1118                   "Failed to load acme-tls/1 pemfile: %s", b->ptr);
1119             break;
1120         }
1121 
1122         buffer_truncate(b, len); /*(remove ".crt.pem")*/
1123         buffer_append_string_len(b, CONST_STR_LEN(".key.pem"));
1124         ssl_pemfile_pkey = malloc(sizeof(*ssl_pemfile_pkey));
1125         force_assert(ssl_pemfile_pkey);
1126         mbedtls_pk_init(ssl_pemfile_pkey);  /* init private key context */
1127         rc = mod_mbedtls_pk_parse_keyfile(ssl_pemfile_pkey, b->ptr, NULL);
1128         if (0 != rc) {
1129             elogf(errh, __FILE__, __LINE__, rc,
1130                   "Failed to load acme-tls/1 pemfile: %s", b->ptr);
1131             break;
1132         }
1133 
1134         rc = mbedtls_ssl_set_hs_own_cert(&hctx->ssl,
1135                                          ssl_pemfile_x509, ssl_pemfile_pkey);
1136         if (0 != rc) {
1137             elogf(errh, __FILE__, __LINE__, rc,
1138                   "failed to set acme-tls/1 certificate for TLS server "
1139                   "name %s", name->ptr);
1140             break;
1141         }
1142 
1143         hctx->acme_tls_1_pkey = ssl_pemfile_pkey; /* save ptr and free later */
1144         hctx->acme_tls_1_x509 = ssl_pemfile_x509; /* save ptr and free later */
1145         return 0;
1146 
1147     } while (0);
1148 
1149     if (ssl_pemfile_pkey) {
1150         mbedtls_pk_free(ssl_pemfile_pkey);
1151         free(ssl_pemfile_pkey);
1152     }
1153     if (ssl_pemfile_x509) {
1154         mbedtls_x509_crt_free(ssl_pemfile_x509);
1155         free(ssl_pemfile_x509);
1156     }
1157 
1158     return rc;
1159 }
1160 #endif
1161 
1162 
1163 static int
1164 mod_mbedtls_alpn_h2_policy (handler_ctx * const hctx)
1165 {
1166     /*(currently called after handshake has completed)*/
1167   #if 0 /* SNI omitted by client when connecting to IP instead of to name */
1168     if (buffer_is_blank(&hctx->r->uri.authority)) {
1169         log_error(hctx->errh, __FILE__, __LINE__,
1170           "SSL: error ALPN h2 without SNI");
1171         return -1;
1172     }
1173   #endif
1174   #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
1175     if (hctx->ssl.major_ver == MBEDTLS_SSL_MAJOR_VERSION_3
1176         && hctx->ssl.minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1177         log_error(hctx->errh, __FILE__, __LINE__,
1178           "SSL: error ALPN h2 requires TLSv1.2 or later");
1179         return -1;
1180     }
1181   #else /*(mbedTLS 3.0.0 dropped support for TLSv1.1 and earlier)*/
1182     UNUSED(hctx);
1183   #endif
1184 
1185     return 0;
1186 }
1187 
1188 
1189 static int
1190 mod_mbedtls_alpn_selected (handler_ctx * const hctx, const char * const in)
1191 {
1192     const int n = (int)strlen(in);
1193     const int i = 0;
1194     unsigned short proto;
1195 
1196     switch (n) {
1197       case 2:  /* "h2" */
1198         if (in[i] == 'h' && in[i+1] == '2') {
1199             proto = MOD_MBEDTLS_ALPN_H2;
1200             if (hctx->r->handler_module == NULL)/*(e.g. not mod_sockproxy)*/
1201                 hctx->r->http_version = HTTP_VERSION_2;
1202             break;
1203         }
1204         return 0;
1205       case 8:  /* "http/1.1" "http/1.0" */
1206         if (0 == memcmp(in+i, "http/1.", 7)) {
1207             if (in[i+7] == '1') {
1208                 proto = MOD_MBEDTLS_ALPN_HTTP11;
1209                 break;
1210             }
1211             if (in[i+7] == '0') {
1212                 proto = MOD_MBEDTLS_ALPN_HTTP10;
1213                 break;
1214             }
1215         }
1216         return 0;
1217       case 10: /* "acme-tls/1" */
1218         if (0 == memcmp(in+i, "acme-tls/1", 10)) {
1219             proto = MOD_MBEDTLS_ALPN_ACME_TLS_1;
1220             break;
1221         }
1222         return 0;
1223       default:
1224         return 0;
1225     }
1226 
1227     hctx->alpn = proto;
1228     return 0;
1229 }
1230 
1231 
1232 #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
1233 #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
1234 static int
1235 mod_mbedtls_alpn_select_cb (handler_ctx *hctx, const unsigned char *in, const unsigned int inlen)
1236 {
1237     /*(skip first two bytes which should match inlen-2)*/
1238     for (unsigned int i = 2, n; i < inlen; i += n) {
1239         n = in[i++];
1240         if (i+n > inlen || 0 == n) break;
1241         switch (n) {
1242           case 2:  /* "h2" */
1243             if (in[i] == 'h' && in[i+1] == '2') {
1244                 if (!hctx->r->conf.h2proto) continue;
1245                 hctx->alpn = MOD_MBEDTLS_ALPN_H2;
1246                 if (hctx->r->handler_module == NULL)/*(e.g. not mod_sockproxy)*/
1247                     hctx->r->http_version = HTTP_VERSION_2;
1248                 return 0;
1249             }
1250             continue;
1251           case 8:  /* "http/1.1" "http/1.0" */
1252             if (0 == memcmp(in+i, "http/1.", 7)) {
1253                 if (in[i+7] == '1') {
1254                     hctx->alpn = MOD_MBEDTLS_ALPN_HTTP11;
1255                     return 0;
1256                 }
1257                 if (in[i+7] == '0') {
1258                     hctx->alpn = MOD_MBEDTLS_ALPN_HTTP10;
1259                     return 0;
1260                 }
1261             }
1262             continue;
1263           case 10: /* "acme-tls/1" */
1264             if (0 == memcmp(in+i, "acme-tls/1", 10)) {
1265                 hctx->alpn = MOD_MBEDTLS_ALPN_ACME_TLS_1;
1266                 return 0;
1267             }
1268             continue;
1269           default:
1270             continue;
1271         }
1272     }
1273 
1274     return 0;
1275 }
1276 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
1277 #endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ /* mbedtls 3.00.0 */
1278 
1279 #endif /* MBEDTLS_SSL_ALPN */
1280 
1281 
1282 #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
1283 static int
1284 mod_mbedtls_cert_cb (mbedtls_ssl_context * const ssl)
1285 {
1286     handler_ctx * const hctx = mbedtls_ssl_get_user_data_p(ssl);
1287     int rc = 0;
1288 
1289   #ifdef MBEDTLS_SSL_ALPN
1290     const char *alpn = mbedtls_ssl_get_alpn_protocol(&hctx->ssl);
1291     if (NULL != alpn) {
1292         rc = mod_mbedtls_alpn_selected(hctx, alpn);
1293         if (0 != rc) return rc;
1294     }
1295   #endif
1296 
1297   #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
1298     size_t len;
1299     const unsigned char *servername = mbedtls_ssl_get_hs_sni(ssl, &len);
1300     if (servername) {
1301         rc = mod_mbedtls_SNI(hctx, ssl, servername, len);
1302         if (0 != rc) return rc;
1303     } /*(else no SNI)*/
1304    #if 0 /*"acme-tls/1" required SNI; use default cert; let cert challenge fail*/
1305     else if (hctx->alpn == MOD_MBEDTLS_ALPN_ACME_TLS_1)
1306         return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
1307    #endif
1308   #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
1309 
1310     if (hctx->conf.ssl_verifyclient
1311         && hctx->alpn != MOD_MBEDTLS_ALPN_ACME_TLS_1) { /*(not "acme-tls/1")*/
1312         rc = mod_mbedtls_conf_verify(hctx);
1313         if (0 != rc) return rc;
1314     }
1315 
1316     return rc;
1317 }
1318 #endif
1319 
1320 
1321 static int
1322 mod_mbedtls_ssl_conf_ciphersuites (server *srv, plugin_config_socket *s, buffer *ciphersuites, const buffer *cipherstring);
1323 
1324 
1325 static int
1326 mod_mbedtls_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *curvelist);
1327 
1328 
1329 static int
1330 mod_mbedtls_ssl_conf_dhparameters(server *srv, plugin_config_socket *s, const buffer *dhparameters);
1331 
1332 
1333 static void
1334 mod_mbedtls_ssl_conf_proto (server *srv, plugin_config_socket *s, const buffer *b, int max);
1335 
1336 
1337 static int
1338 mod_mbedtls_ssl_conf_cmd (server *srv, plugin_config_socket *s)
1339 {
1340     /* reference:
1341      * https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html */
1342     int rc = 0;
1343     buffer *cipherstring = NULL;
1344     buffer *ciphersuites = NULL;
1345 
1346     for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) {
1347         data_string *ds = (data_string *)s->ssl_conf_cmd->data[i];
1348         if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("CipherString")))
1349             cipherstring = &ds->value;
1350         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Ciphersuites")))
1351             ciphersuites = &ds->value;
1352         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Curves"))
1353               || buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Groups"))) {
1354             if (!mod_mbedtls_ssl_conf_curves(srv, s, &ds->value))
1355                 rc = -1;
1356         }
1357         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("DHParameters"))){
1358             if (!buffer_is_blank(&ds->value)) {
1359                 if (!mod_mbedtls_ssl_conf_dhparameters(srv, s, &ds->value))
1360                     rc = -1;
1361             }
1362         }
1363         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MaxProtocol")))
1364             mod_mbedtls_ssl_conf_proto(srv, s, &ds->value, 1); /* max */
1365         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MinProtocol")))
1366             mod_mbedtls_ssl_conf_proto(srv, s, &ds->value, 0); /* min */
1367         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Protocol"))) {
1368             /* openssl config for Protocol=... is complex and deprecated */
1369             log_error(srv->errh, __FILE__, __LINE__,
1370                       "MTLS: ssl.openssl.ssl-conf-cmd %s ignored; "
1371                       "use MinProtocol=... and MaxProtocol=... instead",
1372                       ds->key.ptr);
1373         }
1374         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Options"))) {
1375             for (char *v = ds->value.ptr, *e; *v; v = e) {
1376                 while (*v == ' ' || *v == '\t' || *v == ',') ++v;
1377                 int flag = 1;
1378                 if (*v == '-') {
1379                     flag = 0;
1380                     ++v;
1381                 }
1382                 else if (*v == '+')
1383                     ++v;
1384                 for (e = v; light_isalpha(*e); ++e) ;
1385                 switch ((int)(e-v)) {
1386                   case 11:
1387                     if (buffer_eq_icase_ssn(v, "Compression", 11)) {
1388                         /* mbedtls defaults to no record compression unless
1389                          * mbedtls is built with MBEDTLS_ZLIB_SUPPORT, which
1390                          * is deprecated and slated for removal*/
1391                         if (!flag) continue;
1392                     }
1393                     break;
1394                   case 13:
1395                     if (buffer_eq_icase_ssn(v, "SessionTicket", 13)) {
1396                         s->ssl_session_ticket = flag;
1397                         continue;
1398                     }
1399                     break;
1400                   case 16:
1401                     if (buffer_eq_icase_ssn(v, "ServerPreference", 16)) {
1402                         /* Note: before mbedTLS 3.0.0, the server uses its own
1403                          * preferences over the preference of the client unless
1404                          * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE defined! */
1405                         s->ssl_honor_cipher_order = flag;
1406                         continue;
1407                     }
1408                     break;
1409                   default:
1410                     break;
1411                 }
1412                 /* warn if not explicitly handled or ignored above */
1413                 if (!flag) --v;
1414                 log_error(srv->errh, __FILE__, __LINE__,
1415                           "MTLS: ssl.openssl.ssl-conf-cmd Options %.*s ignored",
1416                           (int)(e-v), v);
1417             }
1418         }
1419       #if 0
1420         else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("..."))) {
1421         }
1422       #endif
1423         else {
1424             /* warn if not explicitly handled or ignored above */
1425             log_error(srv->errh, __FILE__, __LINE__,
1426                       "MTLS: ssl.openssl.ssl-conf-cmd %s ignored",
1427                       ds->key.ptr);
1428         }
1429     }
1430 
1431     if (!mod_mbedtls_ssl_conf_ciphersuites(srv, s, ciphersuites, cipherstring))
1432         rc = -1;
1433 
1434     return rc;
1435 }
1436 
1437 
1438 static int
1439 network_init_ssl (server *srv, plugin_config_socket *s, plugin_data *p)
1440 {
1441     int rc;
1442 
1443     s->ssl_ctx = malloc(sizeof(mbedtls_ssl_config));
1444     force_assert(s->ssl_ctx);
1445     mbedtls_ssl_config_init(s->ssl_ctx);
1446 
1447     /* set the RNG in the ssl config context, using the default random func */
1448     mbedtls_ssl_conf_rng(s->ssl_ctx, mbedtls_ctr_drbg_random, &p->ctr_drbg);
1449 
1450     /* mbedtls defaults to disable client renegotiation
1451      * mbedtls defaults to no record compression unless mbedtls is built
1452      *   with MBEDTLS_ZLIB_SUPPORT, which is deprecated and slated for removal
1453      * MBEDTLS_SSL_PRESET_SUITEB is stricter than MBEDTLS_SSL_PRESET_DEFAULT
1454      * (and is attempted to be supported in mod_mbedtls_ssl_conf_ciphersuites())
1455      * explanation: https://github.com/ARMmbed/mbedtls/issues/1591
1456      * reference: RFC 6460 */
1457     rc = mbedtls_ssl_config_defaults(s->ssl_ctx,
1458                                      MBEDTLS_SSL_IS_SERVER,
1459                                      MBEDTLS_SSL_TRANSPORT_STREAM,
1460                                      MBEDTLS_SSL_PRESET_DEFAULT);
1461     if (0 != rc) {
1462         elog(srv->errh, __FILE__,__LINE__, rc,
1463              "Init of ssl config context defaults failed");
1464         return -1;
1465     }
1466 
1467     if (s->ssl_cipher_list) {
1468         if (!mod_mbedtls_ssl_conf_ciphersuites(srv,s,NULL,s->ssl_cipher_list))
1469             return -1;
1470     }
1471 
1472     /* if needed, attempt to construct certificate chain for server cert */
1473     if (s->pc->need_chain) {
1474         s->pc->need_chain = 0; /*(attempt once to complete chain)*/
1475         if (0 != mod_mbedtls_construct_crt_chain(s->ssl_pemfile_x509,
1476                                                  s->ssl_ca_file, srv->errh))
1477             return -1;
1478     }
1479 
1480     rc = mbedtls_ssl_conf_own_cert(s->ssl_ctx,
1481                                    s->ssl_pemfile_x509, s->ssl_pemfile_pkey);
1482     if (0 != rc) {
1483         elogf(srv->errh, __FILE__, __LINE__, rc,
1484               "PEM cert and private key did not verify (%s) (%s)",
1485               s->ssl_pemfile->ptr, s->ssl_privkey->ptr);
1486         return -1;
1487     }
1488 
1489   #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
1490     mbedtls_ssl_conf_cert_cb(s->ssl_ctx, mod_mbedtls_cert_cb);
1491   #endif
1492 
1493   #ifdef MBEDTLS_SSL_ALPN
1494     /* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids */
1495     static const char *alpn_protos_http_acme[] = {
1496       "h2"
1497      ,"http/1.1"
1498      ,"http/1.0"
1499      ,"acme-tls/1"
1500      ,NULL
1501     };
1502     static const char *alpn_protos_http[] = {
1503       "h2"
1504      ,"http/1.1"
1505      ,"http/1.0"
1506      ,NULL
1507     };
1508     const char **alpn_protos = (s->ssl_acme_tls_1)
1509       ? alpn_protos_http_acme
1510       : alpn_protos_http;
1511     if (!srv->srvconf.h2proto) ++alpn_protos;
1512     rc = mbedtls_ssl_conf_alpn_protocols(s->ssl_ctx, alpn_protos);
1513     if (0 != rc) {
1514         elog(srv->errh, __FILE__, __LINE__, rc, "error setting ALPN protocols");
1515         return -1;
1516     }
1517   #endif
1518 
1519     mod_mbedtls_ssl_conf_proto(srv, s, NULL, 0); /* min */
1520 
1521     if (s->ssl_conf_cmd && s->ssl_conf_cmd->used) {
1522         if (0 != mod_mbedtls_ssl_conf_cmd(srv, s)) return -1;
1523     }
1524 
1525  #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
1526     int order = s->ssl_honor_cipher_order
1527       ? MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER
1528       : MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT;
1529     mbedtls_ssl_conf_preference_order(s->ssl_ctx, order);
1530  #else
1531     /* server preference is used (default) unless mbedtls is built with
1532      * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE defined (not default) */
1533  #endif
1534 
1535   #if defined(MBEDTLS_SSL_SESSION_TICKETS)
1536     if (s->ssl_session_ticket            /*(.ticket_lifetime is private)*/
1537         && !*(unsigned char *)&p->ticket_ctx) { /*init once*/
1538         rc = mbedtls_ssl_ticket_setup(&p->ticket_ctx, mbedtls_ctr_drbg_random,
1539                                       &p->ctr_drbg, MBEDTLS_CIPHER_AES_256_GCM,
1540                                       43200); /* ticket timeout: 12 hours */
1541         if (0 != rc) {
1542             elog(srv->errh,__FILE__,__LINE__,rc,"mbedtls_ssl_ticket_setup()");
1543             return -1;
1544         }
1545     }
1546 
1547    #if defined(MBEDTLS_SSL_TICKET_C)
1548     if (s->ssl_session_ticket)
1549         mbedtls_ssl_conf_session_tickets_cb(s->ssl_ctx,
1550                                             mbedtls_ssl_ticket_write,
1551                                             mbedtls_ssl_ticket_parse,
1552                                             &p->ticket_ctx);
1553    #endif
1554   #endif /* MBEDTLS_SSL_SESSION_TICKETS */
1555 
1556     return 0;
1557 }
1558 
1559 
1560 #define LIGHTTPD_DEFAULT_CIPHER_LIST \
1561 "EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384"
1562 
1563 /*"TLS1-3-AES-256-GCM-SHA384:TLS1-3-CHACHA20-POLY1305-SHA256:TLS1-3-AES-128-GCM-SHA256:TLS1-3-AES-128-CCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-CCM:TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8:TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256"*/
1564 
1565 
1566 static int
1567 mod_mbedtls_set_defaults_sockets(server *srv, plugin_data *p)
1568 {
1569     static const config_plugin_keys_t cpk[] = {
1570       { CONST_STR_LEN("ssl.engine"),
1571         T_CONFIG_BOOL,
1572         T_CONFIG_SCOPE_SOCKET }
1573      ,{ CONST_STR_LEN("ssl.cipher-list"),
1574         T_CONFIG_STRING,
1575         T_CONFIG_SCOPE_SOCKET }
1576      ,{ CONST_STR_LEN("ssl.openssl.ssl-conf-cmd"),
1577         T_CONFIG_ARRAY_KVSTRING,
1578         T_CONFIG_SCOPE_SOCKET }
1579      ,{ CONST_STR_LEN("ssl.pemfile"), /* included to process global scope */
1580         T_CONFIG_STRING,
1581         T_CONFIG_SCOPE_CONNECTION }
1582      ,{ CONST_STR_LEN("ssl.stek-file"),
1583         T_CONFIG_STRING,
1584         T_CONFIG_SCOPE_SERVER }
1585      ,{ NULL, 0,
1586         T_CONFIG_UNSET,
1587         T_CONFIG_SCOPE_UNSET }
1588     };
1589     static const buffer default_ssl_cipher_list =
1590       { CONST_STR_LEN(LIGHTTPD_DEFAULT_CIPHER_LIST), 0 };
1591 
1592     p->ssl_ctxs = calloc(srv->config_context->used, sizeof(plugin_ssl_ctx));
1593     force_assert(p->ssl_ctxs);
1594 
1595     int rc = HANDLER_GO_ON;
1596     plugin_data_base srvplug;
1597     memset(&srvplug, 0, sizeof(srvplug));
1598     plugin_data_base * const ps = &srvplug;
1599     if (!config_plugin_values_init(srv, ps, cpk, "mod_mbedtls"))
1600         return HANDLER_ERROR;
1601 
1602     plugin_config_socket defaults;
1603     memset(&defaults, 0, sizeof(defaults));
1604     defaults.ssl_session_ticket     = 1; /* enabled by default */
1605     defaults.ssl_cipher_list = &default_ssl_cipher_list;
1606 
1607     /* process and validate config directives for global and $SERVER["socket"]
1608      * (init i to 0 if global context; to 1 to skip empty global context) */
1609     for (int i = !ps->cvlist[0].v.u2[1]; i < ps->nconfig; ++i) {
1610         config_cond_info cfginfo;
1611         config_get_config_cond_info(&cfginfo, (uint32_t)ps->cvlist[i].k_id);
1612         int is_socket_scope = (0 == i || cfginfo.comp == COMP_SERVER_SOCKET);
1613         int count_not_engine = 0;
1614 
1615         plugin_config_socket conf;
1616         memcpy(&conf, &defaults, sizeof(conf));
1617         config_plugin_value_t *cpv = ps->cvlist + ps->cvlist[i].v.u2[0];
1618         for (; -1 != cpv->k_id; ++cpv) {
1619             /* ignore ssl.pemfile (k_id=6); included to process global scope */
1620             if (!is_socket_scope && cpv->k_id != 6) {
1621                 log_error(srv->errh, __FILE__, __LINE__,
1622                   "MTLS: %s is valid only in global scope or "
1623                   "$SERVER[\"socket\"] condition", cpk[cpv->k_id].k);
1624                 continue;
1625             }
1626             ++count_not_engine;
1627             switch (cpv->k_id) {
1628               case 0: /* ssl.engine */
1629                 conf.ssl_enabled = (0 != cpv->v.u);
1630                 --count_not_engine;
1631                 break;
1632               case 1: /* ssl.cipher-list */
1633                 if (!buffer_is_blank(cpv->v.b)) {
1634                     conf.ssl_cipher_list = cpv->v.b;
1635                     /*(historical use might list non-PFS ciphers)*/
1636                     conf.ssl_honor_cipher_order = 1;
1637                     log_error(srv->errh, __FILE__, __LINE__,
1638                       "%s is deprecated.  "
1639                       "Please prefer lighttpd secure TLS defaults, or use "
1640                       "ssl.openssl.ssl-conf-cmd \"CipherString\" to set custom "
1641                       "cipher list.", cpk[cpv->k_id].k);
1642                 }
1643                 break;
1644               case 2: /* ssl.openssl.ssl-conf-cmd */
1645                 *(const array **)&conf.ssl_conf_cmd = cpv->v.a;
1646                 break;
1647               case 3: /* ssl.pemfile */
1648                 /* ignore here; included to process global scope when
1649                  * ssl.pemfile is set, but ssl.engine is not "enable" */
1650                 break;
1651               case 4: /* ssl.stek-file */
1652                #ifdef MBEDTLS_SSL_SESSION_TICKETS
1653                 if (!buffer_is_blank(cpv->v.b))
1654                     p->ssl_stek_file = cpv->v.b->ptr;
1655                #else
1656                 log_error(srv->errh, __FILE__, __LINE__, "MTLS: "
1657                   "ssl.stek-file ignored; mbedtls library not built with "
1658                   "support for SSL session tickets");
1659                #endif
1660                 break;
1661               default:/* should not happen */
1662                 break;
1663             }
1664         }
1665         if (HANDLER_GO_ON != rc) break;
1666         if (0 == i) memcpy(&defaults, &conf, sizeof(conf));
1667 
1668         if (0 != i && !conf.ssl_enabled) continue;
1669 
1670         /* fill plugin_config_socket with global context then $SERVER["socket"]
1671          * only for directives directly in current $SERVER["socket"] condition*/
1672 
1673         /*conf.ssl_pemfile_pkey       = p->defaults.ssl_pemfile_pkey;*/
1674         /*conf.ssl_pemfile_x509       = p->defaults.ssl_pemfile_x509;*/
1675         conf.ssl_verifyclient         = p->defaults.ssl_verifyclient;
1676         conf.ssl_verifyclient_enforce = p->defaults.ssl_verifyclient_enforce;
1677         conf.ssl_verifyclient_depth   = p->defaults.ssl_verifyclient_depth;
1678         conf.ssl_acme_tls_1           = p->defaults.ssl_acme_tls_1;
1679 
1680         int sidx = ps->cvlist[i].k_id;
1681         for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) {
1682             if (p->cvlist[j].k_id != sidx) continue;
1683             /*if (0 == sidx) break;*//*(repeat to get ssl_pemfile,ssl_privkey)*/
1684             cpv = p->cvlist + p->cvlist[j].v.u2[0];
1685             for (; -1 != cpv->k_id; ++cpv) {
1686                 ++count_not_engine;
1687                 switch (cpv->k_id) {
1688                   case 0: /* ssl.pemfile */
1689                     if (cpv->vtype == T_CONFIG_LOCAL) {
1690                         plugin_cert *pc = cpv->v.v;
1691                         conf.pc               = pc;
1692                         conf.ssl_pemfile_pkey = &pc->ssl_pemfile_pkey;
1693                         conf.ssl_pemfile_x509 = &pc->ssl_pemfile_x509;
1694                         conf.ssl_pemfile      = pc->ssl_pemfile;
1695                         conf.ssl_privkey      = pc->ssl_privkey;
1696                     }
1697                     break;
1698                   case 2: /* ssl.ca-file */
1699                     if (cpv->vtype == T_CONFIG_LOCAL)
1700                         conf.ssl_ca_file = cpv->v.v;
1701                     break;
1702                   case 7: /* ssl.verifyclient.activate */
1703                     conf.ssl_verifyclient = (0 != cpv->v.u);
1704                     break;
1705                   case 8: /* ssl.verifyclient.enforce */
1706                     conf.ssl_verifyclient_enforce = (0 != cpv->v.u);
1707                     break;
1708                   case 9: /* ssl.verifyclient.depth */
1709                     conf.ssl_verifyclient_depth = (unsigned char)cpv->v.shrt;
1710                     break;
1711                   case 12:/* ssl.acme-tls-1 */
1712                     conf.ssl_acme_tls_1 = cpv->v.b;
1713                     break;
1714                  #if 0    /*(cpk->k_id remapped in mod_mbedtls_set_defaults())*/
1715                   case 14:/* ssl.verifyclient.ca-file */
1716                  #endif
1717                   default:
1718                     break;
1719                 }
1720             }
1721             break;
1722         }
1723 
1724         if (NULL == conf.ssl_pemfile_x509) {
1725             if (0 == i && !conf.ssl_enabled) continue;
1726             if (0 != i) {
1727                 /* inherit ssl settings from global scope
1728                  * (if only ssl.engine = "enable" and no other ssl.* settings)
1729                  * (This is for convenience when defining both IPv4 and IPv6
1730                  *  and desiring to inherit the ssl config from global context
1731                  *  without having to duplicate the directives)*/
1732                 if (count_not_engine
1733                     || (conf.ssl_enabled && NULL == p->ssl_ctxs[0].ssl_ctx)) {
1734                     log_error(srv->errh, __FILE__, __LINE__,
1735                       "MTLS: ssl.pemfile has to be set in same "
1736                       "$SERVER[\"socket\"] scope as other ssl.* directives, "
1737                       "unless only ssl.engine is set, inheriting ssl.* from "
1738                       "global scope");
1739                     rc = HANDLER_ERROR;
1740                     continue;
1741                 }
1742                 plugin_ssl_ctx * const s = p->ssl_ctxs + sidx;
1743                 *s = *p->ssl_ctxs;/*(copy struct of ssl_ctx from global scope)*/
1744                 continue;
1745             }
1746             /* PEM file is required */
1747             log_error(srv->errh, __FILE__, __LINE__,
1748               "MTLS: ssl.pemfile has to be set when ssl.engine = \"enable\"");
1749             rc = HANDLER_ERROR;
1750             continue;
1751         }
1752 
1753         /* (initialize once if module enabled) */
1754         if (!mod_mbedtls_init_once_mbedtls(srv)) {
1755             rc = HANDLER_ERROR;
1756             break;
1757         }
1758 
1759         /* configure ssl_ctx for socket */
1760 
1761         /*conf.ssl_ctx = NULL;*//*(filled by network_init_ssl() even on error)*/
1762         if (0 == network_init_ssl(srv, &conf, p)) {
1763             plugin_ssl_ctx * const s = p->ssl_ctxs + sidx;
1764             s->ssl_ctx            = conf.ssl_ctx;
1765             s->ciphersuites       = conf.ciphersuites;
1766             s->curves             = conf.curves;
1767         }
1768         else {
1769             mbedtls_ssl_config_free(conf.ssl_ctx);
1770             free(conf.ciphersuites);
1771             free(conf.curves);
1772             rc = HANDLER_ERROR;
1773         }
1774     }
1775 
1776   #ifdef MBEDTLS_SSL_SESSION_TICKETS
1777     if (rc == HANDLER_GO_ON && ssl_is_init)
1778         mod_mbedtls_session_ticket_key_check(p, log_epoch_secs);
1779   #endif
1780 
1781     free(srvplug.cvlist);
1782     return rc;
1783 }
1784 
1785 
1786 SETDEFAULTS_FUNC(mod_mbedtls_set_defaults)
1787 {
1788     static const config_plugin_keys_t cpk[] = {
1789       { CONST_STR_LEN("ssl.pemfile"),
1790         T_CONFIG_STRING,
1791         T_CONFIG_SCOPE_CONNECTION }
1792      ,{ CONST_STR_LEN("ssl.privkey"),
1793         T_CONFIG_STRING,
1794         T_CONFIG_SCOPE_CONNECTION }
1795      ,{ CONST_STR_LEN("ssl.ca-file"),
1796         T_CONFIG_STRING,
1797         T_CONFIG_SCOPE_CONNECTION }
1798      ,{ CONST_STR_LEN("ssl.ca-dn-file"),
1799         T_CONFIG_STRING,
1800         T_CONFIG_SCOPE_CONNECTION }
1801      ,{ CONST_STR_LEN("ssl.ca-crl-file"),
1802         T_CONFIG_STRING,
1803         T_CONFIG_SCOPE_CONNECTION }
1804      ,{ CONST_STR_LEN("ssl.read-ahead"),
1805         T_CONFIG_BOOL,
1806         T_CONFIG_SCOPE_CONNECTION }
1807      ,{ CONST_STR_LEN("ssl.disable-client-renegotiation"),
1808         T_CONFIG_BOOL, /*(directive ignored)*/
1809         T_CONFIG_SCOPE_CONNECTION }
1810      ,{ CONST_STR_LEN("ssl.verifyclient.activate"),
1811         T_CONFIG_BOOL,
1812         T_CONFIG_SCOPE_CONNECTION }
1813      ,{ CONST_STR_LEN("ssl.verifyclient.enforce"),
1814         T_CONFIG_BOOL,
1815         T_CONFIG_SCOPE_CONNECTION }
1816      ,{ CONST_STR_LEN("ssl.verifyclient.depth"),
1817         T_CONFIG_SHORT,
1818         T_CONFIG_SCOPE_CONNECTION }
1819      ,{ CONST_STR_LEN("ssl.verifyclient.username"),
1820         T_CONFIG_STRING,
1821         T_CONFIG_SCOPE_CONNECTION }
1822      ,{ CONST_STR_LEN("ssl.verifyclient.exportcert"),
1823         T_CONFIG_BOOL,
1824         T_CONFIG_SCOPE_CONNECTION }
1825      ,{ CONST_STR_LEN("ssl.acme-tls-1"),
1826         T_CONFIG_STRING,
1827         T_CONFIG_SCOPE_CONNECTION }
1828      ,{ CONST_STR_LEN("debug.log-ssl-noise"),
1829         T_CONFIG_BOOL,
1830         T_CONFIG_SCOPE_CONNECTION }
1831      ,{ CONST_STR_LEN("ssl.verifyclient.ca-file"),
1832         T_CONFIG_STRING,
1833         T_CONFIG_SCOPE_CONNECTION }
1834      ,{ CONST_STR_LEN("ssl.verifyclient.ca-dn-file"),
1835         T_CONFIG_STRING,
1836         T_CONFIG_SCOPE_CONNECTION }
1837      ,{ CONST_STR_LEN("ssl.verifyclient.ca-crl-file"),
1838         T_CONFIG_STRING,
1839         T_CONFIG_SCOPE_CONNECTION }
1840      ,{ NULL, 0,
1841         T_CONFIG_UNSET,
1842         T_CONFIG_SCOPE_UNSET }
1843     };
1844 
1845     plugin_data * const p = p_d;
1846     p->srv = srv;
1847     if (!config_plugin_values_init(srv, p, cpk, "mod_mbedtls"))
1848         return HANDLER_ERROR;
1849 
1850     /* process and validate config directives
1851      * (init i to 0 if global context; to 1 to skip empty global context) */
1852     for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
1853         config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
1854         config_plugin_value_t *pemfile = NULL;
1855         config_plugin_value_t *privkey = NULL;
1856         for (; -1 != cpv->k_id; ++cpv) {
1857             switch (cpv->k_id) {
1858               case 0: /* ssl.pemfile */
1859                 if (!buffer_is_blank(cpv->v.b)) pemfile = cpv;
1860                 break;
1861               case 1: /* ssl.privkey */
1862                 if (!buffer_is_blank(cpv->v.b)) privkey = cpv;
1863                 break;
1864               case 14:/* ssl.verifyclient.ca-file */
1865                 if (cpv->k_id == 14) cpv->k_id = 2;
1866                 __attribute_fallthrough__
1867               case 15:/* ssl.verifyclient.ca-dn-file */
1868                 if (cpv->k_id == 15) cpv->k_id = 3;
1869                 __attribute_fallthrough__
1870               case 2: /* ssl.ca-file */
1871               case 3: /* ssl.ca-dn-file */
1872                #if 0 /* defer; not necessary for pemfile parsing */
1873                 if (!mod_mbedtls_init_once_mbedtls(srv)) return HANDLER_ERROR;
1874                #endif
1875                 if (!buffer_is_blank(cpv->v.b)) {
1876                     mbedtls_x509_crt *cacert = calloc(1, sizeof(*cacert));
1877                     force_assert(cacert);
1878                     mbedtls_x509_crt_init(cacert);
1879                     int rc =
1880                       mod_mbedtls_x509_crt_parse_file(cacert, cpv->v.b->ptr);
1881                     if (0 == rc) {
1882                         cpv->vtype = T_CONFIG_LOCAL;
1883                         cpv->v.v = cacert;
1884                     }
1885                     else {
1886                         elogf(srv->errh, __FILE__, __LINE__, rc,
1887                               "%s = %s", cpk[cpv->k_id].k, cpv->v.b->ptr);
1888                         mbedtls_x509_crt_free(cacert);
1889                         free(cacert);
1890                         return HANDLER_ERROR;
1891                     }
1892                 }
1893                 break;
1894               case 16:/* ssl.verifyclient.ca-crl-file */
1895                 cpv->k_id = 4;
1896                 __attribute_fallthrough__
1897               case 4: /* ssl.ca-crl-file */
1898                 if (!buffer_is_blank(cpv->v.b)) {
1899                     mbedtls_x509_crl *crl = malloc(sizeof(*crl));
1900                     force_assert(crl);
1901                     mbedtls_x509_crl_init(crl);
1902                     int rc =
1903                       mod_mbedtls_x509_crl_parse_file(crl, cpv->v.b->ptr);
1904                     if (0 == rc) {
1905                         cpv->vtype = T_CONFIG_LOCAL;
1906                         cpv->v.v = crl;
1907                     }
1908                     else {
1909                         elogf(srv->errh, __FILE__, __LINE__, rc,
1910                               "CRL file read failed (%s)", cpv->v.b->ptr);
1911                         free(crl);
1912                         return HANDLER_ERROR;
1913                     }
1914                 }
1915                 break;
1916               case 5: /* ssl.read-ahead */
1917               case 6: /* ssl.disable-client-renegotiation */
1918                 /*(ignored; unsafe renegotiation disabled by default)*/
1919               case 7: /* ssl.verifyclient.activate */
1920               case 8: /* ssl.verifyclient.enforce */
1921                 break;
1922               case 9: /* ssl.verifyclient.depth */
1923                 if (cpv->v.shrt > 255) {
1924                     log_error(srv->errh, __FILE__, __LINE__,
1925                       "MTLS: %s is absurdly large (%hu); limiting to 255",
1926                       cpk[cpv->k_id].k, cpv->v.shrt);
1927                     cpv->v.shrt = 255;
1928                 }
1929                 break;
1930               case 10:/* ssl.verifyclient.username */
1931                 if (buffer_is_blank(cpv->v.b))
1932                     cpv->v.b = NULL;
1933                 break;
1934               case 11:/* ssl.verifyclient.exportcert */
1935                 break;
1936               case 12:/* ssl.acme-tls-1 */
1937                 if (buffer_is_blank(cpv->v.b))
1938                     cpv->v.b = NULL;
1939                 break;
1940               case 13:/* debug.log-ssl-noise */
1941              #if 0    /*(handled further above)*/
1942               case 14:/* ssl.verifyclient.ca-file */
1943               case 15:/* ssl.verifyclient.ca-dn-file */
1944               case 16:/* ssl.verifyclient.ca-crl-file */
1945              #endif
1946                 break;
1947               default:/* should not happen */
1948                 break;
1949             }
1950         }
1951 
1952         if (pemfile) {
1953             if (NULL == privkey) privkey = pemfile;
1954             pemfile->v.v =
1955               network_mbedtls_load_pemfile(srv, pemfile->v.b, privkey->v.b);
1956             if (pemfile->v.v)
1957                 pemfile->vtype = T_CONFIG_LOCAL;
1958             else
1959                 return HANDLER_ERROR;
1960         }
1961     }
1962 
1963     p->defaults.ssl_verifyclient = 0;
1964     p->defaults.ssl_verifyclient_enforce = 1;
1965     p->defaults.ssl_verifyclient_depth = 9;
1966     p->defaults.ssl_verifyclient_export_cert = 0;
1967     p->defaults.ssl_read_ahead = 0;
1968 
1969     /* initialize p->defaults from global config context */
1970     if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
1971         const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
1972         if (-1 != cpv->k_id)
1973             mod_mbedtls_merge_config(&p->defaults, cpv);
1974     }
1975 
1976   #ifndef MBEDTLS_ERROR_C
1977     log_error(srv->errh, __FILE__, __LINE__,
1978               "MTLS: No error strings available. "
1979               "Compile mbedtls with MBEDTLS_ERROR_C to enable.");
1980   #endif
1981 
1982     return mod_mbedtls_set_defaults_sockets(srv, p);
1983 }
1984 
1985 
1986     /* local_send_buffer is a static buffer of size (LOCAL_SEND_BUFSIZE)
1987      *
1988      * buffer is allocated once, is NOT realloced (note: not thread-safe)
1989      * */
1990 
1991             /* copy small mem chunks into single large buffer
1992              * before mbedtls_ssl_write() to reduce number times
1993              * write() called underneath mbedtls_ssl_write() and
1994              * potentially reduce number of packets generated if TCP_NODELAY */
1995 
1996 
1997 __attribute_cold__
1998 static int
1999 mod_mbedtls_ssl_write_err(connection *con, handler_ctx *hctx, int wr, size_t wr_len)
2000 {
2001     switch (wr) {
2002       case MBEDTLS_ERR_SSL_WANT_READ:
2003         con->is_readable = -1;
2004         break; /* try again later */
2005       case MBEDTLS_ERR_SSL_WANT_WRITE:
2006         con->is_writable = -1;
2007         break; /* try again later */
2008       case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
2009       case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
2010         break; /* try again later */
2011       case MBEDTLS_ERR_NET_CONN_RESET:
2012         if (hctx->conf.ssl_log_noise)
2013             elog(hctx->r->conf.errh, __FILE__, __LINE__, wr,
2014                  "peer closed connection");
2015         return -1;
2016       default:
2017         elog(hctx->r->conf.errh, __FILE__, __LINE__, wr, __func__);
2018         return -1;
2019     }
2020 
2021   #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
2022     if (0 != hctx->ssl.out_left)  /* partial write; save attempted wr_len */
2023   #endif
2024         hctx->pending_write = wr_len;
2025 
2026     return 0; /* try again later */
2027 }
2028 
2029 
2030 static int
2031 mod_mbedtls_close_notify(handler_ctx *hctx);
2032 
2033 
2034 static int
2035 connection_write_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
2036 {
2037     handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
2038     mbedtls_ssl_context * const ssl = &hctx->ssl;
2039 
2040     if (hctx->pending_write) {
2041         int wr = (int)hctx->pending_write;
2042       #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
2043         if (0 != ssl->out_left)
2044       #endif
2045         {
2046             /*(would prefer mbedtls_ssl_flush_output() from ssl_internal.h)*/
2047             size_t data_len = hctx->pending_write;
2048             wr = mbedtls_ssl_write(ssl, NULL, data_len);
2049             if (wr <= 0)
2050                 return mod_mbedtls_ssl_write_err(con, hctx, wr, data_len);
2051             max_bytes -= wr;
2052         }
2053         hctx->pending_write = 0;
2054         chunkqueue_mark_written(cq, wr);
2055     }
2056 
2057     if (__builtin_expect( (0 != hctx->close_notify), 0))
2058         return mod_mbedtls_close_notify(hctx);
2059 
2060     const int lim = mbedtls_ssl_get_max_out_record_payload(ssl);
2061     if (lim < 0) return mod_mbedtls_ssl_write_err(con, hctx, lim, 0);
2062 
2063     log_error_st * const errh = hctx->errh;
2064     while (max_bytes > 0 && !chunkqueue_is_empty(cq)) {
2065         char *data = local_send_buffer;
2066         uint32_t data_len = LOCAL_SEND_BUFSIZE < max_bytes
2067           ? LOCAL_SEND_BUFSIZE
2068           : (uint32_t)max_bytes;
2069         int wr;
2070 
2071         if (0 != chunkqueue_peek_data(cq, &data, &data_len, errh)) return -1;
2072         if (__builtin_expect( (0 == data_len), 0)) {
2073             chunkqueue_remove_finished_chunks(cq);
2074             continue;
2075         }
2076 
2077         /* mbedtls_ssl_write() copies the data, up to max record size, but if
2078          * (temporarily) unable to write the entire record, it is documented
2079          * that the caller must call mbedtls_ssl_write() again, later, with the
2080          * same arguments.  This appears to be because mbedtls_ssl_context does
2081          * not keep track of the original size of the caller data that
2082          * mbedtls_ssl_write() attempted to write (and may have transformed to
2083          * a different size).  The func may return MBEDTLS_ERR_SSL_WANT_READ or
2084          * MBEDTLS_ERR_SSL_WANT_WRITE to indicate that the caller should wait
2085          * for the fd to be readable/writable before calling the func again,
2086          * which is why those (temporary) errors are returned instead of telling
2087          * the caller that the data was successfully copied.  When the record is
2088          * written successfully, the return value is supposed to indicate the
2089          * number of (originally submitted) bytes written, but since that value
2090          * is unknown (not saved), the caller's len parameter is reflected back,
2091          * which is why the caller must call the func again with the same args.
2092          * Additionally, to be accurate, the size must fit into a record which
2093          * is why we restrict ourselves to sending max out record payload each
2094          * iteration.
2095          */
2096 
2097         int wr_total = 0;
2098         do {
2099             size_t wr_len = (data_len > (size_t)lim) ? (size_t)lim : data_len;
2100             wr = mbedtls_ssl_write(ssl, (const unsigned char *)data, wr_len);
2101             if (wr <= 0) {
2102                 if (wr_total) chunkqueue_mark_written(cq, wr_total);
2103                 return mod_mbedtls_ssl_write_err(con, hctx, wr, wr_len);
2104             }
2105             wr_total += wr;
2106             data += wr;
2107         } while ((data_len -= wr));
2108         chunkqueue_mark_written(cq, wr_total);
2109         max_bytes -= wr_total;
2110     }
2111 
2112     return 0;
2113 }
2114 
2115 
2116 #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
2117 #elif MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
2118 #define handshake_state(ssl) (ssl)->MBEDTLS_PRIVATE(state)
2119 #else /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ /* mbedtls 3.00.0 */
2120 #define handshake_state(ssl) (ssl)->state
2121 #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
2122 #ifdef MBEDTLS_SSL_ALPN
2123 static int ssl_parse_client_hello( mbedtls_ssl_context *ssl, handler_ctx *hctx );
2124 #endif
2125 #endif
2126 #endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ /* mbedtls 3.00.0 */
2127 
2128 
2129 static int
2130 mod_mbedtls_ssl_handshake (handler_ctx *hctx)
2131 {
2132     int rc = 0;
2133 
2134  #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
2135 
2136     rc = mbedtls_ssl_handshake(&hctx->ssl);
2137 
2138  #else
2139 
2140     /* overwrite callback with hctx each time we enter here, before handshake
2141      * (Some callbacks are on mbedtls_ssl_config, not mbedtls_ssl_context)
2142      * (Not thread-safe if config (mbedtls_ssl_config *ssl_ctx) is shared)
2143      * (XXX: there is probably a better way to do this...) */
2144   #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
2145     mbedtls_ssl_conf_sni(hctx->ssl_ctx, mod_mbedtls_SNI, hctx);
2146   #endif
2147 
2148     if (handshake_state(&hctx->ssl) < MBEDTLS_SSL_SERVER_HELLO) {
2149         while (handshake_state(&hctx->ssl) != MBEDTLS_SSL_SERVER_HELLO
2150             && handshake_state(&hctx->ssl) != MBEDTLS_SSL_HANDSHAKE_OVER) {
2151           /* disable in mbedtls 3.0+ until alternative callbacks are available
2152            * https://github.com/ARMmbed/mbedtls/issues/5430 */
2153           #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
2154           #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
2155           #ifdef MBEDTLS_SSL_ALPN
2156             /* parse client_hello for ALPN extension prior to mbedtls handshake
2157              * in order to perform certificate selection in mod_mbedtls_SNI() */
2158             if (hctx->conf.ssl_acme_tls_1) {
2159                 rc = ssl_parse_client_hello(&hctx->ssl, hctx);
2160                 if (0 != rc) break;
2161             }
2162           #endif
2163           #endif
2164           #endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ /* mbedtls 3.00.0 */
2165             rc = mbedtls_ssl_handshake_step(&hctx->ssl);
2166             if (0 != rc) break;
2167         }
2168         if (0 == rc
2169             && handshake_state(&hctx->ssl) == MBEDTLS_SSL_SERVER_HELLO) {
2170           #ifdef MBEDTLS_SSL_ALPN
2171             const char *alpn = mbedtls_ssl_get_alpn_protocol(&hctx->ssl);
2172             if (NULL != alpn)
2173                 rc = mod_mbedtls_alpn_selected(hctx, alpn);
2174           #endif
2175         }
2176     }
2177 
2178     if (0 == rc && hctx->conf.ssl_verifyclient  /*(after SNI and ALPN)*/
2179         && handshake_state(&hctx->ssl) >= MBEDTLS_SSL_SERVER_HELLO
2180         && handshake_state(&hctx->ssl) <= MBEDTLS_SSL_SERVER_HELLO_DONE
2181         && hctx->alpn != MOD_MBEDTLS_ALPN_ACME_TLS_1) { /*(not "acme-tls/1")*/
2182         int mode = (hctx->conf.ssl_verifyclient_enforce)
2183           ? MBEDTLS_SSL_VERIFY_REQUIRED
2184           : MBEDTLS_SSL_VERIFY_OPTIONAL;
2185         mbedtls_ssl_set_hs_authmode(&hctx->ssl, mode);
2186         while (handshake_state(&hctx->ssl) != MBEDTLS_SSL_CERTIFICATE_REQUEST
2187             && handshake_state(&hctx->ssl) != MBEDTLS_SSL_HANDSHAKE_OVER) {
2188             rc = mbedtls_ssl_handshake_step(&hctx->ssl);
2189             if (0 != rc) break;
2190         }
2191         if (0 == rc
2192             && handshake_state(&hctx->ssl) == MBEDTLS_SSL_CERTIFICATE_REQUEST) {
2193             rc = mod_mbedtls_conf_verify(hctx);
2194             if (0 == rc)
2195                 rc = mbedtls_ssl_handshake_step(&hctx->ssl);
2196             /* reconfigure CA trust chain after sending client certificate
2197              * request (if ssl_ca_dn_file is set), before client certificate
2198              * verification (MBEDTLS_SSL_CERTIFICATE_VERIFY) */
2199             if (0 == rc && hctx->conf.ssl_ca_dn_file
2200                 && handshake_state(&hctx->ssl)==MBEDTLS_SSL_SERVER_HELLO_DONE) {
2201                 mbedtls_ssl_context * const ssl = &hctx->ssl;
2202                 mbedtls_x509_crt *ca_certs = hctx->conf.ssl_ca_file;
2203                 mbedtls_x509_crl *ca_crl = hctx->conf.ssl_ca_crl_file;
2204                 mbedtls_ssl_set_hs_ca_chain(ssl, ca_certs, ca_crl);
2205             }
2206         }
2207     }
2208 
2209     if (0 == rc && handshake_state(&hctx->ssl) != MBEDTLS_SSL_HANDSHAKE_OVER) {
2210         rc = mbedtls_ssl_handshake(&hctx->ssl);
2211     }
2212 
2213  #endif
2214 
2215     switch (rc) {
2216       case 0:
2217         hctx->handshake_done = 1;
2218        #ifdef MBEDTLS_SSL_ALPN
2219         if (hctx->alpn == MOD_MBEDTLS_ALPN_H2) {
2220             if (0 != mod_mbedtls_alpn_h2_policy(hctx))
2221                 return -1;
2222         }
2223         else if (hctx->alpn == MOD_MBEDTLS_ALPN_ACME_TLS_1) {
2224             /* Once TLS handshake is complete, return -1 to result in
2225              * CON_STATE_ERROR so that socket connection is quickly closed */
2226             return -1;
2227         }
2228         hctx->alpn = 0;
2229        #endif
2230         return 1; /* continue reading */
2231       case MBEDTLS_ERR_SSL_WANT_WRITE:
2232         hctx->con->is_writable = -1;
2233         __attribute_fallthrough__
2234       case MBEDTLS_ERR_SSL_WANT_READ:
2235         hctx->con->is_readable = 0;
2236         return 0;
2237       case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
2238       case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
2239         return 0;
2240       case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
2241         return -1;
2242       case MBEDTLS_ERR_NET_CONN_RESET:
2243       case MBEDTLS_ERR_SSL_CONN_EOF:
2244         if (!hctx->conf.ssl_log_noise) return -1;
2245         __attribute_fallthrough__
2246       default:
2247         elog(hctx->r->conf.errh, __FILE__, __LINE__, rc, __func__);
2248         return -1;
2249     }
2250 }
2251 
2252 
2253 static int
2254 connection_read_cq_ssl (connection * const con, chunkqueue * const cq, off_t max_bytes)
2255 {
2256     handler_ctx * const hctx = con->plugin_ctx[plugin_data_singleton->id];
2257     int len;
2258     char *mem = NULL;
2259     size_t mem_len = 0;
2260 
2261     UNUSED(max_bytes);
2262 
2263     if (__builtin_expect( (0 != hctx->close_notify), 0))
2264         return mod_mbedtls_close_notify(hctx);
2265 
2266     if (!hctx->handshake_done) {
2267         int rc = mod_mbedtls_ssl_handshake(hctx);
2268         if (1 != rc) return rc; /* !hctx->handshake_done; not done, or error */
2269     }
2270 
2271     do {
2272         len = mbedtls_ssl_get_bytes_avail(&hctx->ssl);
2273         mem_len = len < 2048 ? 2048 : (size_t)len;
2274         chunk * const ckpt = cq->last;
2275         mem = chunkqueue_get_memory(cq, &mem_len);
2276 
2277         len = mbedtls_ssl_read(&hctx->ssl, (unsigned char *)mem, mem_len);
2278         chunkqueue_use_memory(cq, ckpt, len > 0 ? len : 0);
2279     } while (len > 0
2280              && mbedtls_ssl_check_pending(&hctx->ssl));
2281 
2282     if (len < 0) {
2283         int rc = len;
2284         request_st * const r = &con->request;
2285         switch (rc) {
2286           case MBEDTLS_ERR_SSL_WANT_WRITE:
2287             con->is_writable = -1;
2288             __attribute_fallthrough__
2289           case MBEDTLS_ERR_SSL_WANT_READ:
2290             con->is_readable = 0;
2291             return 0;
2292           case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
2293           case MBEDTLS_ERR_SSL_CONN_EOF:
2294             /* XXX: future: save state to avoid future read after response? */
2295             con->is_readable = 0;
2296             r->keep_alive = 0;
2297             return -2;
2298           case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
2299           case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
2300             return 0;
2301           case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
2302             return -1;
2303           case MBEDTLS_ERR_NET_CONN_RESET:
2304             if (!hctx->conf.ssl_log_noise) return -1;
2305             __attribute_fallthrough__
2306           default:
2307             elog(hctx->errh, __FILE__, __LINE__, rc, "Reading mbedtls");
2308             return -1;
2309         }
2310     } else if (len == 0) {
2311         con->is_readable = 0;
2312         /* the other end closed the connection -> KEEP-ALIVE */
2313 
2314         return -2;
2315     } else {
2316         return 0;
2317     }
2318 }
2319 
2320 
2321 static void
2322 mod_mbedtls_debug_cb(void *ctx, int level,
2323                      const char *file, int line,
2324                      const char *str)
2325 {
2326     if (level < (intptr_t)ctx) /* level */
2327         log_error(plugin_data_singleton->srv->errh,file,line,"MTLS: %s",str);
2328 }
2329 
2330 
2331 CONNECTION_FUNC(mod_mbedtls_handle_con_accept)
2332 {
2333     const server_socket *srv_sock = con->srv_socket;
2334     if (!srv_sock->is_ssl) return HANDLER_GO_ON;
2335 
2336     plugin_data *p = p_d;
2337     handler_ctx * const hctx = handler_ctx_init();
2338     request_st * const r = &con->request;
2339     hctx->r = r;
2340     hctx->con = con;
2341     hctx->tmp_buf = con->srv->tmp_buf;
2342     hctx->errh = r->conf.errh;
2343     con->plugin_ctx[p->id] = hctx;
2344     buffer_blank(&r->uri.authority);
2345 
2346     hctx->ssl_ctx = p->ssl_ctxs[srv_sock->sidx].ssl_ctx;
2347     mbedtls_ssl_init(&hctx->ssl);
2348     int rc = mbedtls_ssl_setup(&hctx->ssl, hctx->ssl_ctx);
2349     if (0 == rc) {
2350         con->network_read = connection_read_cq_ssl;
2351         con->network_write = connection_write_cq_ssl;
2352         con->proto_default_port = 443; /* "https" */
2353         mod_mbedtls_patch_config(r, &hctx->conf);
2354     }
2355     else {
2356         elog(r->conf.errh, __FILE__, __LINE__, rc, "ssl_setup() failed");
2357         return HANDLER_ERROR;
2358     }
2359 
2360   #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
2361     mbedtls_ssl_set_user_data_p(&hctx->ssl, hctx);
2362   #endif
2363 
2364     mbedtls_ssl_set_bio(&hctx->ssl, (mbedtls_net_context *)&con->fd,
2365                         mbedtls_net_send, mbedtls_net_recv, NULL);
2366 
2367     /* (mbedtls_ssl_config *) is shared across multiple connections, which may
2368      * overlap, and so this debug setting is not reset upon connection close.
2369      * Once enabled, debug hook will remain so for this mbedtls_ssl_config */
2370     if (hctx->conf.ssl_log_noise) {/* volume level for debug message callback */
2371       #if MBEDTLS_VERSION_NUMBER >= 0x02000000 /* mbedtls 2.0.0 */
2372         mbedtls_debug_set_threshold(hctx->conf.ssl_log_noise);
2373       #endif
2374         mbedtls_ssl_conf_dbg(hctx->ssl_ctx, mod_mbedtls_debug_cb,
2375                              (void *)(intptr_t)hctx->conf.ssl_log_noise);
2376     }
2377 
2378     return HANDLER_GO_ON;
2379 }
2380 
2381 
2382 static void
2383 mod_mbedtls_detach(handler_ctx *hctx)
2384 {
2385     /* step aside from further SSL processing
2386      * (used after handle_connection_shut_wr hook) */
2387     /* future: might restore prior network_read and network_write fn ptrs */
2388     hctx->con->is_ssl_sock = 0;
2389     /* if called after handle_connection_shut_wr hook, shutdown SHUT_WR */
2390     if (-1 == hctx->close_notify) shutdown(hctx->con->fd, SHUT_WR);
2391     hctx->close_notify = 1;
2392 }
2393 
2394 
2395 CONNECTION_FUNC(mod_mbedtls_handle_con_shut_wr)
2396 {
2397     plugin_data *p = p_d;
2398     handler_ctx *hctx = con->plugin_ctx[p->id];
2399     if (NULL == hctx) return HANDLER_GO_ON;
2400 
2401     hctx->close_notify = -2;
2402     if (hctx->handshake_done) {
2403         mod_mbedtls_close_notify(hctx);
2404     }
2405     else {
2406         mod_mbedtls_detach(hctx);
2407     }
2408 
2409     return HANDLER_GO_ON;
2410 }
2411 
2412 
2413 static int
2414 mod_mbedtls_close_notify (handler_ctx *hctx)
2415 {
2416     if (1 == hctx->close_notify) return -2;
2417 
2418     int rc = mbedtls_ssl_close_notify(&hctx->ssl);
2419     switch (rc) {
2420       case 0:
2421         mod_mbedtls_detach(hctx);
2422         return -2;
2423       case MBEDTLS_ERR_SSL_WANT_READ:
2424       case MBEDTLS_ERR_SSL_WANT_WRITE:
2425         return 0;
2426       default:
2427         elog(hctx->r->conf.errh, __FILE__, __LINE__, rc,
2428              "mbedtls_ssl_close_notify()");
2429         __attribute_fallthrough__
2430       case MBEDTLS_ERR_NET_CONN_RESET:
2431         mbedtls_ssl_session_reset(&hctx->ssl);
2432         mod_mbedtls_detach(hctx);
2433         return -1;
2434     }
2435 }
2436 
2437 
2438 CONNECTION_FUNC(mod_mbedtls_handle_con_close)
2439 {
2440     plugin_data *p = p_d;
2441     handler_ctx *hctx = con->plugin_ctx[p->id];
2442     if (NULL != hctx) {
2443         con->plugin_ctx[p->id] = NULL;
2444         if (1 != hctx->close_notify)
2445             mod_mbedtls_close_notify(hctx); /*(one final try)*/
2446         handler_ctx_free(hctx);
2447     }
2448 
2449     return HANDLER_GO_ON;
2450 }
2451 
2452 
2453 #if defined(MBEDTLS_PEM_WRITE_C)
2454 __attribute_noinline__
2455 static void
2456 https_add_ssl_client_cert (request_st * const r, const mbedtls_x509_crt * const peer)
2457 {
2458     #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
2459     #define PEM_END_CRT   "-----END CERTIFICATE-----\n"
2460     unsigned char buf[4096];
2461     size_t olen;
2462     if (0 == mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT,
2463                                       peer->raw.p, peer->raw.len,
2464                                       buf, sizeof(buf), &olen))
2465         http_header_env_set(r,
2466                             CONST_STR_LEN("SSL_CLIENT_CERT"),
2467                             (char *)buf, olen);
2468 }
2469 #endif
2470 
2471 
2472 static void
2473 https_add_ssl_client_subject (request_st * const r, const mbedtls_x509_name *name)
2474 {
2475     /* add components of client Subject DN */
2476     /* code block is similar to mbedtls_x509_dn_gets() */
2477     /* code block specialized for creating env vars of Subject DN components
2478      * and splits multi-valued RDNs into separate env vars for attribute=value*/
2479     size_t n = 0;
2480     const size_t prelen = sizeof("SSL_CLIENT_S_DN_")-1;
2481     char key[64] = "SSL_CLIENT_S_DN_";
2482     char buf[512]; /* MBEDTLS_X509_MAX_DN_NAME_SIZE is (256) */
2483 
2484     for (; name != NULL; name = name->next) {
2485         if (!name->oid.p)
2486             continue;
2487         const char *short_name = NULL;
2488         if (0 != mbedtls_oid_get_attr_short_name(&name->oid, &short_name))
2489             continue;
2490         const size_t len = strlen(short_name);
2491         if (prelen+len >= sizeof(key)) continue;
2492         memcpy(key+prelen, short_name, len); /*(not '\0'-terminated)*/
2493 
2494         if (n+2+len+1+name->val.len > sizeof(buf)) continue;
2495         buf[n++] = ','; /*(", " at beginning is skipped outside loop below)*/
2496         buf[n++] = ' ';
2497         memcpy(buf+n, short_name, len);
2498         n += len;
2499         buf[n++] = '=';
2500 
2501         for (size_t i = 0; i < name->val.len; ++i) {
2502             unsigned char c = name->val.p[i];
2503             buf[n+i] = (c >= 32 && c != 127) ? c : '?';
2504         }
2505 
2506         http_header_env_set(r, key, prelen+len, buf+n, name->val.len);
2507         n += name->val.len;
2508     }
2509 
2510     /* mbedtls_x509_dn_gets() is not used to construct DN because that func does
2511      * not support non-ASCII UTF-8.  This func allows non-ASCII UTF-8 but does
2512      * not check for need to backslash-encode special chars.  This func
2513      * *assumes* a trusted and validated cert which does contain any chars which
2514      * need to be backslash-encoded in the stringified DN, even if such chars
2515      * are allowed in ASN.1 DN.  Above, CTLs are encoded as '?' above, even
2516      * though some are allowed if backslash-encoded.  Multi-valued RDNs are not
2517      * combined with '+' above, as name->next_merged is private in mbedtls 3.0.0
2518      */
2519     if (n > 2)
2520         http_header_env_set(r, CONST_STR_LEN("SSL_CLIENT_S_DN"), buf+2, n-2);
2521 }
2522 
2523 
2524 __attribute_cold__
2525 static void
2526 https_add_ssl_client_verify_err (buffer * const b, uint32_t status)
2527 {
2528   #ifndef MBEDTLS_X509_REMOVE_INFO
2529     /* get failure string and translate newline to ':', removing last one */
2530     char buf[512];
2531     int n = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", status);
2532     if (n > 0) {
2533         for (char *nl = buf; NULL != (nl = strchr(nl, '\n')); ++nl)
2534             nl[0] = ('\0' == nl[1] ? (--n, '\0') : ':');
2535         buffer_append_string_len(b, buf, n);
2536     }
2537   #else
2538     UNUSED(b);
2539     UNUSED(status);
2540   #endif
2541 }
2542 
2543 
2544 __attribute_noinline__
2545 static void
2546 https_add_ssl_client_entries (request_st * const r, handler_ctx * const hctx)
2547 {
2548     /* Note: starting with mbedtls-2.17.0, peer cert is not available here if
2549      * MBEDTLS_SSL_KEEP_PEER_CERTIFICATE *is not* defined at compile time,
2550      * though default behavior is to have it defined.  However, since earlier
2551      * versions do keep the cert, but not set this define, attempt to retrieve
2552      * the peer cert and check for NULL before using it. */
2553     const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&hctx->ssl);
2554     buffer *vb = http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_VERIFY"));
2555 
2556     uint32_t rc = (NULL != crt)
2557       ? mbedtls_ssl_get_verify_result(&hctx->ssl)
2558       : 0xFFFFFFFF;
2559     if (0xFFFFFFFF == rc) { /*(e.g. no cert, or verify result not available)*/
2560         buffer_copy_string_len(vb, CONST_STR_LEN("NONE"));
2561         return;
2562     }
2563     else if (0 != rc) {
2564         buffer_copy_string_len(vb, CONST_STR_LEN("FAILED:"));
2565         https_add_ssl_client_verify_err(vb, rc);
2566         return;
2567     }
2568     else {
2569         buffer_copy_string_len(vb, CONST_STR_LEN("SUCCESS"));
2570     }
2571 
2572     https_add_ssl_client_subject(r, &crt->subject);
2573 
2574     /* mbedtls_x509_serial_gets() (inefficiently) formats to hex separated by
2575      * colons, but would differ from behavior of other lighttpd TLS modules */
2576     size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */
2577     while (i < crt->serial.len && crt->serial.p[i] == 0) ++i;
2578     if (i == crt->serial.len) --i;
2579     buffer_append_string_encoded_hex_uc(
2580       http_header_env_set_ptr(r, CONST_STR_LEN("SSL_CLIENT_M_SERIAL")),
2581       (char *)crt->serial.p+i, crt->serial.len-i);
2582 
2583     if (hctx->conf.ssl_verifyclient_username) {
2584         /* pick one of the exported values as "REMOTE_USER", for example
2585          *   ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID"
2586          * or
2587          *   ssl.verifyclient.username = "SSL_CLIENT_S_DN_emailAddress"
2588          */
2589         const buffer *varname = hctx->conf.ssl_verifyclient_username;
2590         vb = http_header_env_get(r, BUF_PTR_LEN(varname));
2591         if (vb) { /* same as mod_auth_api.c:http_auth_setenv() */
2592             http_header_env_set(r,
2593                                 CONST_STR_LEN("REMOTE_USER"),
2594                                 BUF_PTR_LEN(vb));
2595             http_header_env_set(r,
2596                                 CONST_STR_LEN("AUTH_TYPE"),
2597                                 CONST_STR_LEN("SSL_CLIENT_VERIFY"));
2598         }
2599     }
2600 
2601   #if defined(MBEDTLS_PEM_WRITE_C)
2602     /* if (NULL != crt) (e.g. not PSK-based ciphersuite) */
2603     if (hctx->conf.ssl_verifyclient_export_cert)
2604         https_add_ssl_client_cert(r, crt);
2605   #endif
2606 }
2607 
2608 
2609 #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.02.0 */
2610 #define mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl) \
2611         (ssl)->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(ciphersuite)
2612 #define mbedtls_ssl_ciphersuite_get_name(info) \
2613         (info)->MBEDTLS_PRIVATE(name)
2614 #endif
2615 
2616 static void
2617 http_cgi_ssl_env (request_st * const r, handler_ctx * const hctx)
2618 {
2619     const char *s;
2620 
2621     s = mbedtls_ssl_get_version(&hctx->ssl);
2622     http_header_env_set(r, CONST_STR_LEN("SSL_PROTOCOL"), s, strlen(s));
2623 
2624     const int ciphersuite_id =
2625       mbedtls_ssl_get_ciphersuite_id_from_ssl(&hctx->ssl);
2626     const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
2627       mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
2628     if (__builtin_expect( (NULL == ciphersuite_info), 0)) return;
2629 
2630     s = mbedtls_ssl_ciphersuite_get_name(ciphersuite_info);
2631     http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER"), s, strlen(s));
2632 
2633     {
2634         /* SSL_CIPHER_ALGKEYSIZE - Number of cipher bits (possible) */
2635         /* SSL_CIPHER_USEKEYSIZE - Number of cipher bits (actually used) */
2636       #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.02.0 */
2637         size_t algkeysize =
2638           mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(ciphersuite_info);
2639         unsigned int usekeysize = algkeysize; /*(equivalent in modern ciphers)*/
2640       #elif MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.00.0 */
2641        #ifdef MBEDTLS_CIPHER_C
2642         /*(messy transition; ssl->transform is hidden in ssl_internal.h)*/
2643         const mbedtls_cipher_info_t * const cipher_info =
2644           mbedtls_cipher_info_from_type(
2645             ciphersuite_info->MBEDTLS_PRIVATE(cipher));
2646         if (__builtin_expect( (NULL == cipher_info), 0)) return;
2647         unsigned int algkeysize = cipher_info->MBEDTLS_PRIVATE(key_bitlen);
2648        #else
2649         if (1) return;
2650        #endif
2651         unsigned int usekeysize = algkeysize; /*(equivalent in modern ciphers)*/
2652       #else
2653         /* XXX: is usekeysize correct? XXX: reaching into ssl_internal.h here */
2654         unsigned int usekeysize =
2655           hctx->ssl.transform->cipher_ctx_enc.key_bitlen;
2656        #ifdef MBEDTLS_CIPHER_C
2657         unsigned int algkeysize =
2658           hctx->ssl.transform->cipher_ctx_enc.cipher_info->key_bitlen;
2659        #else
2660         unsigned int algkeysize = usekeysize;
2661        #endif
2662       #endif
2663         char buf[LI_ITOSTRING_LENGTH];
2664         http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_ALGKEYSIZE"),
2665                             buf, li_utostrn(buf, sizeof(buf), algkeysize));
2666         http_header_env_set(r, CONST_STR_LEN("SSL_CIPHER_USEKEYSIZE"),
2667                             buf, li_utostrn(buf, sizeof(buf), usekeysize));
2668     }
2669 }
2670 
2671 
2672 REQUEST_FUNC(mod_mbedtls_handle_request_env)
2673 {
2674     plugin_data *p = p_d;
2675     /* simple flag for request_env_patched */
2676     if (r->plugin_ctx[p->id]) return HANDLER_GO_ON;
2677     handler_ctx *hctx = r->con->plugin_ctx[p->id];
2678     if (NULL == hctx) return HANDLER_GO_ON;
2679     r->plugin_ctx[p->id] = (void *)(uintptr_t)1u;
2680 
2681     http_cgi_ssl_env(r, hctx);
2682     if (hctx->conf.ssl_verifyclient) {
2683         https_add_ssl_client_entries(r, hctx);
2684     }
2685 
2686     return HANDLER_GO_ON;
2687 }
2688 
2689 
2690 REQUEST_FUNC(mod_mbedtls_handle_uri_raw)
2691 {
2692     /* mod_mbedtls must be loaded prior to mod_auth
2693      * if mod_mbedtls is configured to set REMOTE_USER based on client cert */
2694     /* mod_mbedtls must be loaded after mod_extforward
2695      * if mod_mbedtls config is based on lighttpd.conf remote IP conditional
2696      * using remote IP address set by mod_extforward, *unless* PROXY protocol
2697      * is enabled with extforward.hap-PROXY = "enable", in which case the
2698      * reverse is true: mod_extforward must be loaded after mod_mbedtls */
2699     plugin_data *p = p_d;
2700     handler_ctx *hctx = r->con->plugin_ctx[p->id];
2701     if (NULL == hctx) return HANDLER_GO_ON;
2702 
2703     mod_mbedtls_patch_config(r, &hctx->conf);
2704     if (hctx->conf.ssl_verifyclient) {
2705         mod_mbedtls_handle_request_env(r, p);
2706     }
2707 
2708     return HANDLER_GO_ON;
2709 }
2710 
2711 
2712 REQUEST_FUNC(mod_mbedtls_handle_request_reset)
2713 {
2714     plugin_data *p = p_d;
2715     r->plugin_ctx[p->id] = NULL; /* simple flag for request_env_patched */
2716     return HANDLER_GO_ON;
2717 }
2718 
2719 
2720 TRIGGER_FUNC(mod_mbedtls_handle_trigger) {
2721     plugin_data * const p = p_d;
2722     const unix_time64_t cur_ts = log_epoch_secs;
2723     if (cur_ts & 0x3f) return HANDLER_GO_ON; /*(continue once each 64 sec)*/
2724     UNUSED(srv);
2725     UNUSED(p);
2726 
2727   #ifdef MBEDTLS_SSL_SESSION_TICKETS
2728     mod_mbedtls_session_ticket_key_check(p, cur_ts);
2729   #endif
2730 
2731     return HANDLER_GO_ON;
2732 }
2733 
2734 
2735 __attribute_cold__
2736 int mod_mbedtls_plugin_init (plugin *p);
2737 int mod_mbedtls_plugin_init (plugin *p)
2738 {
2739     p->version      = LIGHTTPD_VERSION_ID;
2740     p->name         = "mbedtls";
2741     p->init         = mod_mbedtls_init;
2742     p->cleanup      = mod_mbedtls_free;
2743     p->priv_defaults= mod_mbedtls_set_defaults;
2744 
2745     p->handle_connection_accept  = mod_mbedtls_handle_con_accept;
2746     p->handle_connection_shut_wr = mod_mbedtls_handle_con_shut_wr;
2747     p->handle_connection_close   = mod_mbedtls_handle_con_close;
2748     p->handle_uri_raw            = mod_mbedtls_handle_uri_raw;
2749     p->handle_request_env        = mod_mbedtls_handle_request_env;
2750     p->handle_request_reset      = mod_mbedtls_handle_request_reset;
2751     p->handle_trigger            = mod_mbedtls_handle_trigger;
2752 
2753     return 0;
2754 }
2755 
2756 
2757 /* cipher suites (taken from mbedtls/ssl_ciphersuites.[ch]) */
2758 
2759 static const int suite_CHACHAPOLY_ephemeral[] = {
2760     /* Chacha-Poly ephemeral suites */
2761     MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
2762     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
2763     MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
2764 };
2765 
2766 static const int suite_AES_256_ephemeral[] = {
2767     /* All AES-256 ephemeral suites */
2768     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
2769     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
2770     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
2771     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
2772     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
2773     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
2774     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
2775     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
2776     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
2777     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
2778     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
2779     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
2780     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8
2781 };
2782 
2783 static const int suite_CAMELLIA_256_ephemeral[] = {
2784     /* All CAMELLIA-256 ephemeral suites */
2785     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
2786     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
2787     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
2788     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
2789     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
2790     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
2791     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
2792 };
2793 
2794 static const int suite_ARIA_256_ephemeral[] = {
2795     /* All ARIA-256 ephemeral suites */
2796     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
2797     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
2798     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
2799     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
2800     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
2801     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384
2802 };
2803 
2804 static const int suite_AES_128_ephemeral[] = {
2805     /* All AES-128 ephemeral suites */
2806     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
2807     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
2808     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
2809     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
2810     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
2811     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
2812     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
2813     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
2814     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
2815     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
2816     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
2817     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
2818     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8
2819 };
2820 
2821 static const int suite_CAMELLIA_128_ephemeral[] = {
2822     /* All CAMELLIA-128 ephemeral suites */
2823     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
2824     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
2825     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
2826     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
2827     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
2828     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
2829     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
2830 };
2831 
2832 static const int suite_ARIA_128_ephemeral[] = {
2833     /* All ARIA-128 ephemeral suites */
2834     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
2835     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
2836     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
2837     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
2838     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
2839     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256
2840 };
2841 
2842 static const int suite_PSK_ephemeral[] = {
2843     /* The PSK ephemeral suites */
2844     MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
2845     MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
2846     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
2847     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
2848     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
2849     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
2850     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
2851     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
2852     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,
2853     MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
2854     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
2855     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
2856     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
2857     MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
2858     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
2859 
2860     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
2861     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
2862     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
2863     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
2864     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
2865     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
2866     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,
2867     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
2868     MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
2869     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
2870     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
2871     MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
2872     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256
2873 };
2874 
2875 #if 0
2876 static const int suite_ECJPAKE[] = {
2877     /* The ECJPAKE suite */
2878     MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
2879 };
2880 #endif
2881 
2882 static const int suite_AES_256[] = {
2883     /* All AES-256 suites */
2884     MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
2885     MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
2886     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
2887     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
2888     MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
2889     MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
2890     MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
2891     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
2892     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
2893     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
2894     MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8
2895 };
2896 
2897 static const int suite_CAMELLIA_256[] = {
2898     /* All CAMELLIA-256 suites */
2899     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
2900     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
2901     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
2902     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
2903     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
2904     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
2905     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
2906 };
2907 
2908 static const int suite_ARIA_256[] = {
2909     /* All ARIA-256 suites */
2910     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
2911     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
2912     MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
2913     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
2914     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
2915     MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384
2916 };
2917 
2918 static const int suite_AES_128[] = {
2919     /* All AES-128 suites */
2920     MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
2921     MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
2922     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
2923     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
2924     MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
2925     MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
2926     MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
2927     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
2928     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
2929     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
2930     MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8
2931 };
2932 
2933 static const int suite_CAMELLIA_128[] = {
2934     /* All CAMELLIA-128 suites */
2935     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
2936     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
2937     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
2938     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
2939     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
2940     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
2941     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
2942 };
2943 
2944 static const int suite_ARIA_128[] = {
2945     /* All ARIA-128 suites */
2946     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
2947     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
2948     MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
2949     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
2950     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
2951     MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256
2952 };
2953 
2954 static const int suite_RSA_PSK[] = {
2955     /* The RSA PSK suites */
2956     MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
2957     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
2958     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
2959     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
2960     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
2961     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
2962     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
2963     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
2964 
2965     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
2966     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
2967     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
2968     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
2969     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
2970     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
2971     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256
2972 };
2973 
2974 static const int suite_PSK[] = {
2975     /* The PSK suites */
2976     MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
2977     MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
2978     MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
2979     MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
2980     MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
2981     MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
2982     MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
2983     MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
2984     MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
2985     MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
2986 
2987     MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
2988     MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
2989     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
2990     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
2991     MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
2992     MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
2993     MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
2994     MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
2995     MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256
2996 };
2997 
2998 #ifdef MBEDTLS_SSL_PROTO_TLS1
2999 static const int suite_3DES[] = {
3000     /* 3DES suites */
3001     MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
3002     MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
3003     MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
3004     MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
3005     MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
3006     MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
3007     MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
3008     MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
3009     MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
3010     MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
3011 };
3012 #endif
3013 
3014 #ifdef MBEDTLS_SSL_PROTO_TLS1
3015 static const int suite_RC4[] = {
3016     /* RC4 suites */
3017     MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
3018     MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
3019     MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
3020     MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA,
3021     MBEDTLS_TLS_RSA_WITH_RC4_128_SHA,
3022     MBEDTLS_TLS_RSA_WITH_RC4_128_MD5,
3023     MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA,
3024     MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
3025     MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA,
3026     MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
3027 };
3028 #endif
3029 
3030 #ifdef MBEDTLS_SSL_PROTO_SSL3
3031 static const int suite_weak[] = {
3032     /* Weak suites */
3033     MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA,
3034     MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA
3035 };
3036 #endif
3037 
3038 static const int suite_null[] = {
3039     /* NULL suites */
3040     MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
3041     MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA,
3042     MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384,
3043     MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256,
3044     MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA,
3045     MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384,
3046     MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256,
3047     MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA,
3048 
3049     MBEDTLS_TLS_RSA_WITH_NULL_SHA256,
3050     MBEDTLS_TLS_RSA_WITH_NULL_SHA,
3051     MBEDTLS_TLS_RSA_WITH_NULL_MD5,
3052     MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA,
3053     MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA,
3054     MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384,
3055     MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256,
3056     MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA,
3057     MBEDTLS_TLS_PSK_WITH_NULL_SHA384,
3058     MBEDTLS_TLS_PSK_WITH_NULL_SHA256,
3059     MBEDTLS_TLS_PSK_WITH_NULL_SHA
3060 };
3061 
3062 /* TLSv1.2 cipher list (supported in mbedtls)
3063  * marked with minimum version MBEDTLS_SSL_MINOR_VERSION_3 in
3064  *   ciphersuite_definitions[] and then sorted by ciphersuite_preference[]
3065  *   from mbedtls library/ssl_ciphersuites.c */
3066 static const int suite_TLSv12[] = {
3067     MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
3068     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
3069     MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
3070     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
3071     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
3072     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
3073     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
3074     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
3075     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
3076     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
3077     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
3078     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
3079     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8,
3080     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
3081     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
3082     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
3083     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
3084     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
3085     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
3086     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
3087     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
3088     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
3089     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
3090     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
3091     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
3092     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
3093     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
3094     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
3095     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
3096     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
3097     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
3098     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
3099     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
3100     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
3101     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
3102     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
3103     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3104     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
3105     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
3106     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
3107     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
3108     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
3109     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
3110     MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
3111     MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
3112     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
3113     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
3114     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,
3115     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
3116     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
3117     MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
3118     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
3119     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
3120     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
3121     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,
3122     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
3123     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
3124     MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
3125     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
3126     MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8,
3127     MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
3128     MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
3129     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
3130     MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
3131     MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
3132     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
3133     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
3134     MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
3135     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
3136     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
3137     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
3138     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
3139     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
3140     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
3141     MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
3142     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
3143     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
3144     MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
3145     MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
3146     MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
3147     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
3148     MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
3149     MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
3150     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
3151     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
3152     MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
3153     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
3154     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3155     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
3156     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
3157     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
3158     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
3159     MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
3160     MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
3161     MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
3162     MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
3163     MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
3164     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
3165     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
3166     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
3167     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
3168     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
3169     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
3170     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
3171     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
3172     MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
3173     MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
3174     MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
3175     MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
3176     MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
3177     MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
3178     MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
3179     MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
3180     MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
3181     MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
3182     MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
3183     MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
3184     MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256
3185 };
3186 
3187 #ifdef MBEDTLS_SSL_PROTO_TLS1
3188 /* TLSv1.0 cipher list (supported in mbedtls)
3189  * marked with minimum version MBEDTLS_SSL_MINOR_VERSION_1 in
3190  *   ciphersuite_definitions[] and then sorted by ciphersuite_preference[]
3191  *   from mbedtls library/ssl_ciphersuites.c */
3192 /* XXX: intentionally not including overlapping eNULL ciphers */
3193 static const int suite_TLSv10[] = {
3194     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
3195     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
3196     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
3197     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
3198     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
3199     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
3200     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
3201     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3202     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
3203     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
3204     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
3205     MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3206     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3207     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
3208     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
3209     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
3210     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3211     MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3212     MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
3213     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
3214     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
3215     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
3216     MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
3217     MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
3218     MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3219     MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
3220     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
3221     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
3222     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3223     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
3224     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
3225     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3226     MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
3227     MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3228     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
3229     MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3230     MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
3231     MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
3232     MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
3233     MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
3234     MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
3235     MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
3236     MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
3237     MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
3238     MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
3239     MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA,
3240     MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
3241     MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
3242 };
3243 #endif
3244 
3245 /* HIGH cipher list (mapped from openssl list to mbedtls) */
3246 static const int suite_HIGH[] = {
3247     MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
3248     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
3249     MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
3250     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
3251     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
3252     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
3253     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
3254     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
3255     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
3256     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
3257     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
3258     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
3259     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
3260     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
3261     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
3262     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8,
3263     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
3264     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
3265     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
3266     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
3267     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
3268     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
3269     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
3270     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
3271     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
3272     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
3273     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
3274     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
3275     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
3276     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
3277     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
3278     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
3279     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
3280     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
3281     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
3282     MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
3283     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
3284     MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3285     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3286     MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
3287     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
3288     MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
3289     MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
3290     MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
3291     MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
3292     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
3293     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
3294     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
3295     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
3296     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
3297     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
3298     MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3299     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3300     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
3301     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
3302     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
3303     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
3304     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
3305     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
3306     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
3307     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
3308     MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3309     MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3310     MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
3311     MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
3312     MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
3313     MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
3314     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
3315     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
3316     MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
3317     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
3318     MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
3319     MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
3320     MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
3321     MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
3322     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
3323     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
3324     MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
3325     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
3326     MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
3327     MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
3328     MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
3329     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
3330     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
3331     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
3332     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3333     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
3334     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
3335     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
3336     MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
3337     MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3338     MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
3339     MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
3340     MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
3341     MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
3342     MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
3343     MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
3344     MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
3345     MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
3346     MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
3347     MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
3348     MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
3349     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
3350     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
3351     MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
3352     MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
3353     MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
3354 };
3355 
3356 
3357 /* true if RC4 or weak or NULL cipher suite
3358  *   (These ciphersuites are excluded from openssl "DEFAULT")
3359  * This is a subset of ciphers excluded for mod_openssl "!aNULL:!eNULL:!EXP" */
3360 static int
3361 mod_mbedtls_ssl_is_weak_ciphersuite (int id)
3362 {
3363   #ifdef MBEDTLS_SSL_PROTO_TLS1
3364     for (uint32_t i = 0; i < sizeof(suite_RC4)/sizeof(suite_RC4[0]); ++i) {
3365         if (id == suite_RC4[i]) return 1;
3366     }
3367   #endif
3368   #ifdef MBEDTLS_SSL_PROTO_SSL3
3369     for (uint32_t i = 0; i < sizeof(suite_weak)/sizeof(suite_weak[0]); ++i) {
3370         if (id == suite_weak[i]) return 1;
3371     }
3372   #endif
3373     for (uint32_t i = 0; i < sizeof(suite_null)/sizeof(suite_null[0]); ++i) {
3374         if (id == suite_null[i]) return 1;
3375     }
3376     return 0;
3377 }
3378 
3379 
3380 static int
3381 mod_mbedtls_ssl_DEFAULT_ciphersuite (server *srv, int *ids, int nids, int idsz)
3382 {
3383     /* obtain default ciphersuite list and filter out weak or NULL */
3384     const int *dids = mbedtls_ssl_list_ciphersuites();
3385     int i = 0;
3386     while (dids[i] != 0) ++i;
3387 
3388     if (i >= idsz - (nids + 1)) {
3389         log_error(srv->errh, __FILE__, __LINE__,
3390           "MTLS: error: too many ciphersuites during list expand");
3391         return -1;
3392     }
3393 
3394     for (i = 0; dids[i] != 0; ++i) {
3395         if (!mod_mbedtls_ssl_is_weak_ciphersuite(dids[i]))
3396             ids[++nids] = dids[i];
3397     }
3398 
3399     return nids;
3400 }
3401 
3402 
3403 static int
3404 mod_mbedtls_ssl_append_ciphersuite (server *srv, int *ids, int nids, int idsz, const int *x, int xsz)
3405 {
3406     if (xsz >= idsz - (nids + 1)) {
3407         log_error(srv->errh, __FILE__, __LINE__,
3408           "MTLS: error: too many ciphersuites during list expand");
3409         return -1;
3410     }
3411 
3412     for (int i = 0; i < xsz; ++i)
3413         ids[++nids] = x[i];
3414 
3415     return nids;
3416 }
3417 
3418 
3419 static int
3420 mod_mbedtls_ssl_conf_ciphersuites (server *srv, plugin_config_socket *s, buffer *ciphersuites, const buffer *cipherstring)
3421 {
3422     /* reference: https://www.openssl.org/docs/man1.1.1/man1/ciphers.html
3423      * Attempt to parse *some* keywords from Ciphersuites and CipherString
3424      * !!! openssl uses a *different* naming scheme than does mbedTLS !!!
3425      * Since Ciphersuites in openssl takes only TLSv1.3 suites, and mbedTLS
3426      * does not currently support TLSv1.3, mapping of those names is not
3427      * currently provided.  Note that CipherString does allow cipher suites to
3428      * be listed, and this code does not currently attempt to provide mapping */
3429 
3430     char n[128]; /*(most ciphersuite names are about 40 chars)*/
3431     int ids[512];
3432     int nids = -1;
3433     const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
3434     int crt_profile_default = 0;
3435 
3436     if (ciphersuites) {
3437         buffer *b = ciphersuites;
3438         buffer_to_upper(b); /*(ciphersuites are all uppercase (currently))*/
3439         for (const char *e = b->ptr-1; e; ) {
3440             const char * const p = e+1;
3441             e = strchr(p, ':');
3442             size_t len = e ? (size_t)(e - p) : strlen(p);
3443             if (len >= sizeof(n)) {
3444                 log_error(srv->errh, __FILE__, __LINE__,
3445                   "MTLS: skipped ciphersuite; too long: %.*s",
3446                   (int)len, p);
3447                 continue;
3448             }
3449             memcpy(n, p, len);
3450             n[len] = '\0';
3451 
3452             int id = mbedtls_ssl_get_ciphersuite_id(n);
3453             if (0 == id) {
3454                 log_error(srv->errh, __FILE__, __LINE__,
3455                   "MTLS: skipped ciphersuite; not recognized: %.*s",
3456                   (int)len, n);
3457                 continue;
3458             }
3459 
3460             /* allow any ciphersuite if explicitly listed, even weak or eNULL */
3461           #if 0
3462             if (mod_mbedtls_ssl_is_weak_ciphersuite(id)) {
3463                 log_error(srv->errh, __FILE__, __LINE__,
3464                   "MTLS: skipped ciphersuite; weak or NULL suite: %.*s",
3465                   (int)len, n);
3466                 continue;
3467             }
3468           #endif
3469 
3470             if (nids >= idsz) {
3471                 log_error(srv->errh, __FILE__, __LINE__,
3472                   "MTLS: skipped ciphersuite; too many listed: %.*s",
3473                   (int)len, n);
3474                 continue;
3475             }
3476 
3477             ids[++nids] = id;
3478         }
3479     }
3480 
3481     /* XXX: openssl config for CipherString=... is excessively complex.
3482      * If there is a need to enable specific ciphersuites, then that
3483      * can be accomplished with mod_mbedtls by specifying the list in
3484      * Ciphersuites=... in the ssl.openssl.ssl-conf-cmd directive.
3485      * (Alternatively, build mbedtls with specific set of cipher suites
3486      *  or modify mod_mbedtls code to specify the precise list).
3487      *
3488      * The tokens parsed here are a quick attempt to handle a few cases
3489      *
3490      * XXX: not done: could make a list of ciphers with bitflag of attributes
3491      *      to make future combining easier */
3492     if (cipherstring && !buffer_is_blank(cipherstring)) {
3493         const buffer *b = cipherstring;
3494         const char *e = b->ptr;
3495 
3496         /* XXX: not done: no checking for duplication of ciphersuites
3497          * even if tokens overlap or are repeated */
3498 
3499         /* XXX: not done: might walk string and build up exclude list of !xxxxx
3500          * ciphersuites and walk string again, excluding as result list built */
3501 
3502         /* manually handle first token, since one-offs apply */
3503         /* (openssl syntax NOT fully supported) */
3504         int default_suite = 0;
3505         #define strncmp_const(s,cs) strncmp((s),(cs),sizeof(cs)-1)
3506         if (0 == strncmp_const(e, "!ALL") || 0 == strncmp_const(e, "-ALL")) {
3507             /* "!ALL" excluding all ciphers does not make sense; ignore */
3508             e += sizeof("!ALL")-1; /* same as sizeof("-ALL")-1 */
3509         }
3510         else if (0 == strncmp_const(e, "!DEFAULT")
3511               || 0 == strncmp_const(e, "-DEFAULT")) {
3512             /* "!DEFAULT" excluding default ciphers is empty list; no effect */
3513             e += sizeof("!DEFAULT")-1; /* same as sizeof("-DEFAULT")-1 */
3514         }
3515         else if (0 == strncmp_const(e, "DEFAULT")) {
3516             e += sizeof("DEFAULT")-1;
3517             default_suite = 1;
3518         }
3519         else if (0 == /* effectively the same as "DEFAULT" */
3520                  strncmp_const(e, "ALL:!COMPLEMENTOFDEFAULT:!eNULL")) {
3521             e += sizeof("ALL:!COMPLEMENTOFDEFAULT:!eNULL")-1;
3522             default_suite = 1;
3523         }
3524         else if (0 == strncmp_const(e, "SUITEB128")
3525               || 0 == strncmp_const(e, "SUITEB128ONLY")
3526               || 0 == strncmp_const(e, "SUITEB192")) {
3527             mbedtls_ssl_conf_cert_profile(s->ssl_ctx,
3528                                           &mbedtls_x509_crt_profile_suiteb);
3529             /* re-initialize mbedtls_ssl_config defaults */
3530           #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.02.0 */
3531             mbedtls_mpi_free(&s->ssl_ctx->MBEDTLS_PRIVATE(dhm_P));
3532             mbedtls_mpi_free(&s->ssl_ctx->MBEDTLS_PRIVATE(dhm_G));
3533           #endif
3534             int rc = mbedtls_ssl_config_defaults(s->ssl_ctx,
3535                                                  MBEDTLS_SSL_IS_SERVER,
3536                                                  MBEDTLS_SSL_TRANSPORT_STREAM,
3537                                                  MBEDTLS_SSL_PRESET_SUITEB);
3538             if (0 != rc) {
3539                 elog(srv->errh, __FILE__,__LINE__, rc,
3540                      "Init of ssl config context SUITEB defaults failed");
3541                 return 0;
3542             }
3543             if (0 == strncmp_const(e, "SUITEB192")) {
3544                 static const int ssl_preset_suiteb192[] = {
3545                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
3546                     0
3547                 };
3548                 static const mbedtls_x509_crt_profile crt_profile_suiteb192 = {
3549                     /* Only SHA-384 */
3550                     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
3551                     /* Only ECDSA */
3552                     MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
3553                     MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
3554                   #if defined(MBEDTLS_ECP_C)
3555                     /* Only NIST P-384 */
3556                     MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
3557                   #else
3558                     0,
3559                   #endif
3560                     3072,
3561                 };
3562                 mbedtls_ssl_conf_ciphersuites(s->ssl_ctx, ssl_preset_suiteb192);
3563                 mbedtls_ssl_conf_cert_profile(s->ssl_ctx,
3564                                               &crt_profile_suiteb192);
3565                 mbedtls_ssl_conf_dhm_min_bitlen(s->ssl_ctx, 3072);
3566             }
3567             e += (0 == strncmp_const(e, "SUITEB128ONLY"))
3568                  ? sizeof("SUITEB128ONLY")-1
3569                  : sizeof("SUITEB128")-1;
3570             if (*e)
3571                 log_error(srv->errh, __FILE__, __LINE__,
3572                   "MTLS: ignoring cipher string after SUITEB: %s", e);
3573             return 1;
3574         }
3575         else if (0 == strncmp_const(e,
3576                   "ECDHE+AESGCM:ECDHE+AES256:CHACHA20:!SHA1:!SHA256:!SHA384")
3577               || 0 == strncmp_const(e,
3578                   "EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384")) {
3579             e += sizeof(
3580                   "EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384")-1;
3581           #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
3582             if (nids + 13 >= idsz)
3583           #else
3584             if (nids + 9 >= idsz)
3585           #endif
3586             {
3587                 log_error(srv->errh, __FILE__, __LINE__,
3588                   "MTLS: error: too many ciphersuites during list expand");
3589                 return 0;
3590             }
3591           #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
3592             ids[++nids] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384;
3593             ids[++nids] = MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256;
3594             ids[++nids] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256;
3595             ids[++nids] = MBEDTLS_TLS1_3_AES_128_CCM_SHA256;
3596           #endif
3597             ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
3598             ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
3599             ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
3600             ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
3601             ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM;
3602             ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
3603             ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
3604             ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
3605             ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
3606         }
3607 
3608         if (e != b->ptr && *e != ':' && *e != '\0') {
3609             log_error(srv->errh, __FILE__, __LINE__,
3610               "MTLS: error: missing support for cipher list: %s", b->ptr);
3611             return 0;
3612         }
3613 
3614         if (default_suite) {
3615             crt_profile_default = 1;
3616             nids =
3617               mod_mbedtls_ssl_DEFAULT_ciphersuite(srv, ids, nids, idsz);
3618             if (-1 == nids) return 0;
3619         }
3620 
3621         /* not handled: "ALL" is "DEFAULT" and "RC4" */
3622         /* not handled: "COMPLEMENTOFALL" is "eNULL" */
3623 
3624         int rc = 1;
3625         if (e == b->ptr || *e == '\0') --e; /*initial condition for loop below*/
3626         do {
3627             const char * const p = e+1;
3628             e = strchr(p, ':');
3629             size_t len = e ? (size_t)(e - p) : strlen(p);
3630             if (0 == len) continue;
3631             if (len >= sizeof(n)) {
3632                 log_error(srv->errh, __FILE__, __LINE__,
3633                   "MTLS: skipped ciphersuite; too long: %.*s",
3634                   (int)len, p);
3635                 continue;
3636             }
3637             char c = (*p == '!' || *p == '-' || *p == '+') ? *p : 0;
3638             size_t nlen = c ? len-1 : len;
3639             memcpy(n, c ? p+1 : p, nlen);
3640             n[nlen] = '\0';
3641 
3642             /* not handled: !xxxxx -xxxxx and most +xxxxx */
3643             if (c) {
3644                 log_error(srv->errh, __FILE__, __LINE__,
3645                   "MTLS: error: missing support for cipher list: %s", b->ptr);
3646             }
3647 
3648             /* ignore @STRENGTH sorting and ignore @SECLEVEL=n */
3649             char *a = strchr(n, '@');
3650             if (a) {
3651                 log_error(srv->errh, __FILE__, __LINE__,
3652                   "MTLS: ignored %s in %.*s", a, (int)len, p);
3653                 *a = '\0';
3654                 nlen = (size_t)(a - n);
3655             }
3656 
3657             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("TLSv1.2"))) {
3658                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3659                          suite_TLSv12,
3660                          (int)(sizeof(suite_TLSv12)/sizeof(*suite_TLSv12)));
3661                 if (-1 == nids) return 0;
3662                 continue;
3663             }
3664 
3665           #ifdef MBEDTLS_SSL_PROTO_TLS1
3666             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("TLSv1.0"))) {
3667                 crt_profile_default = 1;
3668                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3669                          suite_TLSv10,
3670                          (int)(sizeof(suite_TLSv10)/sizeof(*suite_TLSv10)));
3671                 if (-1 == nids) return 0;
3672                 continue;
3673             }
3674           #endif
3675 
3676             /* handle popular recommendations
3677              *   ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM"
3678              *   ssl.cipher-list = "AES256+EECDH:AES256+EDH"
3679              * which uses AES hardware acceleration built into popular CPUs */
3680             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("ECDHE+AESGCM"))
3681              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("EECDH+AESGCM"))) {
3682               #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
3683                 if (nids + 6 >= idsz)
3684               #else
3685                 if (nids + 4 >= idsz)
3686               #endif
3687                 {
3688                     log_error(srv->errh, __FILE__, __LINE__,
3689                       "MTLS: error: too many ciphersuites during list expand");
3690                     return 0;
3691                 }
3692               #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
3693                 ids[++nids] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384;
3694                 ids[++nids] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256;
3695               #endif
3696                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
3697                 ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
3698                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
3699                 ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
3700                 continue;
3701             }
3702             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("DHE+AESGCM"))
3703              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("EDH+AESGCM"))) {
3704                 if (nids + 2 >= idsz) {
3705                     log_error(srv->errh, __FILE__, __LINE__,
3706                       "MTLS: error: too many ciphersuites during list expand");
3707                     return 0;
3708                 }
3709                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
3710                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
3711                 continue;
3712             }
3713             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("AES256+EECDH"))) {
3714               #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
3715                 if (nids + 9 >= idsz)
3716               #else
3717                 if (nids + 8 >= idsz)
3718               #endif
3719                 {
3720                     log_error(srv->errh, __FILE__, __LINE__,
3721                       "MTLS: error: too many ciphersuites during list expand");
3722                     return 0;
3723                 }
3724               #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
3725                 ids[++nids] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384;
3726               #endif
3727                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
3728                 ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
3729                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM;
3730                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
3731                 ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
3732                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
3733                 ids[++nids] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
3734                 ids[++nids] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
3735                 continue;
3736             }
3737             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("AES256+EDH"))) {
3738                 if (nids + 5 >= idsz) {
3739                     log_error(srv->errh, __FILE__, __LINE__,
3740                       "MTLS: error: too many ciphersuites during list expand");
3741                     return 0;
3742                 }
3743                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
3744                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM;
3745                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
3746                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
3747                 ids[++nids] = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8;
3748                 continue;
3749             }
3750 
3751             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("HIGH"))) {
3752                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3753                          suite_HIGH,
3754                          (int)(sizeof(suite_HIGH)/sizeof(*suite_HIGH)));
3755                 if (-1 == nids) return 0;
3756                 continue;
3757             }
3758 
3759             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("AES256"))
3760              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("AES"))) {
3761                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3762                          suite_AES_256_ephemeral,
3763                          (int)(sizeof(suite_AES_256_ephemeral)
3764                               /sizeof(*suite_AES_256_ephemeral)));
3765                 if (-1 == nids) return 0;
3766                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3767                          suite_AES_256,
3768                          (int)(sizeof(suite_AES_256)/sizeof(*suite_AES_256)));
3769                 if (-1 == nids) return 0;
3770                 /* XXX: not done: AES256 PSK suites */
3771                 if (nlen == sizeof("AES256")-1) continue;
3772             }
3773 
3774             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("AES128"))
3775              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("AES"))) {
3776                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3777                          suite_AES_128_ephemeral,
3778                          (int)(sizeof(suite_AES_128_ephemeral)
3779                               /sizeof(*suite_AES_128_ephemeral)));
3780                 if (-1 == nids) return 0;
3781                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3782                          suite_AES_128,
3783                          (int)(sizeof(suite_AES_128)/sizeof(*suite_AES_128)));
3784                 if (-1 == nids) return 0;
3785                 /* XXX: not done: AES128 PSK suites */
3786                 continue;
3787             }
3788 
3789             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("CAMELLIA256"))
3790              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("CAMELLIA"))) {
3791                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3792                          suite_CAMELLIA_256_ephemeral,
3793                          (int)(sizeof(suite_CAMELLIA_256_ephemeral)
3794                               /sizeof(*suite_CAMELLIA_256_ephemeral)));
3795                 if (-1 == nids) return 0;
3796                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3797                          suite_CAMELLIA_256,
3798                          (int)(sizeof(suite_CAMELLIA_256)
3799                               /sizeof(*suite_CAMELLIA_256)));
3800                 if (-1 == nids) return 0;
3801                 /* XXX: not done: CAMELLIA256 PSK suites */
3802                 if (nlen == sizeof("CAMELLIA256")-1) continue;
3803             }
3804 
3805             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("CAMELLIA128"))
3806              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("CAMELLIA"))) {
3807                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3808                          suite_CAMELLIA_128_ephemeral,
3809                          (int)(sizeof(suite_CAMELLIA_128_ephemeral)
3810                               /sizeof(*suite_CAMELLIA_128_ephemeral)));
3811                 if (-1 == nids) return 0;
3812                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3813                          suite_CAMELLIA_128,
3814                          (int)(sizeof(suite_CAMELLIA_128)
3815                               /sizeof(*suite_CAMELLIA_128)));
3816                 if (-1 == nids) return 0;
3817                 /* XXX: not done: CAMELLIA128 PSK suites */
3818                 continue;
3819             }
3820 
3821             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("ARIA256"))
3822              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("ARIA"))) {
3823                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3824                          suite_ARIA_256_ephemeral,
3825                          (int)(sizeof(suite_ARIA_256_ephemeral)
3826                               /sizeof(*suite_ARIA_256_ephemeral)));
3827                 if (-1 == nids) return 0;
3828                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3829                          suite_ARIA_256,
3830                          (int)(sizeof(suite_ARIA_256)/sizeof(*suite_ARIA_256)));
3831                 if (-1 == nids) return 0;
3832                 /* XXX: not done: ARIA256 PSK suites */
3833                 if (nlen == sizeof("ARIA256")-1) continue;
3834             }
3835 
3836             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("ARIA128"))
3837              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("ARIA"))) {
3838                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3839                          suite_ARIA_128_ephemeral,
3840                          (int)(sizeof(suite_ARIA_128_ephemeral)
3841                               /sizeof(*suite_ARIA_128_ephemeral)));
3842                 if (-1 == nids) return 0;
3843                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3844                          suite_ARIA_128,
3845                          (int)(sizeof(suite_ARIA_128)/sizeof(*suite_ARIA_128)));
3846                 if (-1 == nids) return 0;
3847                 /* XXX: not done: ARIA128 PSK suites */
3848                 continue;
3849             }
3850 
3851             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("CHACHA20"))) {
3852                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3853                          suite_CHACHAPOLY_ephemeral,
3854                          (int)(sizeof(suite_CHACHAPOLY_ephemeral)
3855                               /sizeof(*suite_CHACHAPOLY_ephemeral)));
3856                 if (-1 == nids) return 0;
3857                 /* XXX: not done: CHACHA20 PSK suites */
3858                 continue;
3859             }
3860 
3861             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("PSK"))) {
3862                 /* XXX: intentionally not including overlapping eNULL ciphers */
3863                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3864                          suite_PSK_ephemeral,
3865                          (int)(sizeof(suite_PSK_ephemeral)
3866                               /sizeof(*suite_PSK_ephemeral)));
3867                 if (-1 == nids) return 0;
3868                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3869                          suite_RSA_PSK,
3870                          (int)(sizeof(suite_RSA_PSK)/sizeof(*suite_RSA_PSK)));
3871                 if (-1 == nids) return 0;
3872                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3873                          suite_PSK,
3874                          (int)(sizeof(suite_PSK)/sizeof(*suite_PSK)));
3875                 if (-1 == nids) return 0;
3876                 continue;
3877             }
3878 
3879           #ifdef MBEDTLS_SSL_PROTO_TLS1
3880             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("3DES"))) {
3881                 crt_profile_default = 1;
3882                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3883                          suite_3DES,
3884                          (int)(sizeof(suite_3DES)/sizeof(*suite_3DES)));
3885                 if (-1 == nids) return 0;
3886                 continue;
3887             }
3888           #endif
3889 
3890           #ifdef MBEDTLS_SSL_PROTO_TLS1
3891             /* not recommended, but permitted if explicitly requested */
3892             /* "RC4" is same as openssl "COMPLEMENTOFALL" */
3893             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("RC4"))) {
3894                 crt_profile_default = 1;
3895                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3896                          suite_RC4,
3897                          (int)(sizeof(suite_RC4)/sizeof(*suite_RC4)));
3898                 if (-1 == nids) return 0;
3899                 continue;
3900             }
3901           #endif
3902 
3903             /* not recommended, but permitted if explicitly requested */
3904             if (buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("NULL"))
3905              || buffer_eq_icase_ss(n, nlen, CONST_STR_LEN("eNULL"))) {
3906                 crt_profile_default = 1;
3907                 nids = mod_mbedtls_ssl_append_ciphersuite(srv, ids, nids, idsz,
3908                          suite_null,
3909                          (int)(sizeof(suite_null)/sizeof(*suite_null)));
3910                 if (-1 == nids) return 0;
3911                 continue;
3912             }
3913 
3914             const mbedtls_ssl_ciphersuite_t *info =
3915               mbedtls_ssl_ciphersuite_from_string(n);
3916             if (info) {
3917                 if (nids + 1 >= idsz) {
3918                     log_error(srv->errh, __FILE__, __LINE__,
3919                       "MTLS: error: too many ciphersuites during list expand");
3920                     return 0;
3921                 }
3922                 /* WTH?  why private and no accessor func? */
3923                 ids[++nids] = info->MBEDTLS_PRIVATE(id);
3924                 continue;
3925             }
3926 
3927             {
3928                 log_error(srv->errh, __FILE__, __LINE__,
3929                   "MTLS: error: missing support for cipher list: %.*s",
3930                   (int)len, p);
3931                 rc = 0;
3932                 continue;
3933             }
3934         } while (e);
3935         if (0 == rc) return 0;
3936     }
3937 
3938     if (-1 == nids) {
3939         /* Do not set a default if ssl.cipher-list was set (and we are
3940          * are processing ssl.openssl.ssl-conf-cmd, not ssl.cipher-list) */
3941         if (cipherstring != s->ssl_cipher_list && s->ssl_cipher_list)
3942             return 1;
3943 
3944         /* obtain default ciphersuite list and filter out RC4, weak, and NULL */
3945         nids =
3946           mod_mbedtls_ssl_DEFAULT_ciphersuite(srv, ids, nids,
3947                                               sizeof(ids)/sizeof(*ids));
3948         if (-1 == nids) return 0;
3949     }
3950 
3951     if (nids >= idsz) {
3952         log_error(srv->errh, __FILE__, __LINE__,
3953           "MTLS: error: too many ciphersuites during list expand");
3954         return 0;
3955     }
3956     ids[++nids] = 0; /* terminate list */
3957     ++nids;
3958 
3959     if (!crt_profile_default)
3960         mbedtls_ssl_conf_cert_profile(s->ssl_ctx,
3961                                       &mbedtls_x509_crt_profile_next);
3962 
3963     /* ciphersuites list must be persistent for lifetime of mbedtls_ssl_config*/
3964     free(s->ciphersuites);
3965     s->ciphersuites = malloc(nids * sizeof(int));
3966     force_assert(s->ciphersuites);
3967     memcpy(s->ciphersuites, ids, nids * sizeof(int));
3968 
3969     mbedtls_ssl_conf_ciphersuites(s->ssl_ctx, s->ciphersuites);
3970     return 1;
3971 }
3972 
3973 
3974 #if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.01.0 */
3975 static int
3976 mod_mbedtls_ssl_append_curve (server *srv, mbedtls_ecp_group_id *ids, int nids, int idsz, const mbedtls_ecp_group_id id)
3977 {
3978     if (1 >= idsz - (nids + 1)) {
3979         log_error(srv->errh, __FILE__, __LINE__,
3980           "MTLS: error: too many curves during list expand");
3981         return -1;
3982     }
3983     ids[++nids] = id;
3984     return nids;
3985 }
3986 
3987 
3988 static int
3989 mod_mbedtls_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *curvelist)
3990 {
3991     mbedtls_ecp_group_id ids[512];
3992     int nids = -1;
3993     const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
3994     const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
3995 
3996     const buffer * const b = curvelist;
3997     for (const char *e = b->ptr-1; e; ) {
3998         const char * const n = e+1;
3999         e = strchr(n, ':');
4000         size_t len = e ? (size_t)(e - n) : strlen(n);
4001         /* similar to mbedtls_ecp_curve_info_from_name() */
4002         const mbedtls_ecp_curve_info *info;
4003         for (info = curve_info; info->grp_id != MBEDTLS_ECP_DP_NONE; ++info) {
4004             if (0 == strncmp(info->name, n, len) && info->name[len] == '\0')
4005                 break;
4006         }
4007         if (info->grp_id == MBEDTLS_ECP_DP_NONE) {
4008             log_error(srv->errh, __FILE__, __LINE__,
4009                       "MTLS: unrecognized curve: %.*s; ignored", (int)len, n);
4010             continue;
4011         }
4012 
4013         nids = mod_mbedtls_ssl_append_curve(srv, ids, nids, idsz, info->grp_id);
4014         if (-1 == nids) return 0;
4015     }
4016 
4017     /* XXX: mod_openssl configures "prime256v1" if curve list not specified,
4018      * but mbedtls provides a list of supported curves if not explicitly set */
4019     if (-1 == nids) return 1; /* empty list; no-op */
4020 
4021     ids[++nids] = MBEDTLS_ECP_DP_NONE; /* terminate list */
4022     ++nids;
4023 
4024     /* curves list must be persistent for lifetime of mbedtls_ssl_config */
4025     s->curves = malloc(nids * sizeof(mbedtls_ecp_group_id));
4026     force_assert(s->curves);
4027     memcpy(s->curves, ids, nids * sizeof(mbedtls_ecp_group_id));
4028 
4029     mbedtls_ssl_conf_curves(s->ssl_ctx, s->curves);
4030     return 1;
4031 }
4032 #else
4033 static int
4034 mod_mbedtls_ssl_append_curve (server *srv, uint16_t *ids, int nids, int idsz, const uint16_t id)
4035 {
4036     if (1 >= idsz - (nids + 1)) {
4037         log_error(srv->errh, __FILE__, __LINE__,
4038           "MTLS: error: too many curves during list expand");
4039         return -1;
4040     }
4041     ids[++nids] = id;
4042     return nids;
4043 }
4044 
4045 
4046 static int
4047 mod_mbedtls_ssl_conf_curves(server *srv, plugin_config_socket *s, const buffer *curvelist)
4048 {
4049     uint16_t ids[512];
4050     int nids = -1;
4051     const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
4052     const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
4053 
4054     const buffer * const b = curvelist;
4055     for (const char *e = b->ptr-1; e; ) {
4056         const char * const n = e+1;
4057         e = strchr(n, ':');
4058         size_t len = e ? (size_t)(e - n) : strlen(n);
4059         /* similar to mbedtls_ecp_curve_info_from_name() */
4060         const mbedtls_ecp_curve_info *info;
4061         for (info = curve_info; info->tls_id != 0; ++info) {
4062             if (0 == strncmp(info->name, n, len) && info->name[len] == '\0')
4063                 break;
4064         }
4065         if (info->tls_id == 0) {
4066             log_error(srv->errh, __FILE__, __LINE__,
4067                       "MTLS: unrecognized curve: %.*s; ignored", (int)len, n);
4068             continue;
4069         }
4070 
4071         nids = mod_mbedtls_ssl_append_curve(srv, ids, nids, idsz, info->tls_id);
4072         if (-1 == nids) return 0;
4073     }
4074 
4075     /* XXX: mod_openssl configures "prime256v1" if curve list not specified,
4076      * but mbedtls provides a list of supported curves if not explicitly set */
4077     if (-1 == nids) return 1; /* empty list; no-op */
4078 
4079     ids[++nids] = 0; /* terminate list */
4080     ++nids;
4081 
4082     /* curves list must be persistent for lifetime of mbedtls_ssl_config */
4083     s->curves = malloc(nids * sizeof(uint16_t));
4084     force_assert(s->curves);
4085     memcpy(s->curves, ids, nids * sizeof(uint16_t));
4086 
4087     mbedtls_ssl_conf_groups(s->ssl_ctx, s->curves);
4088     return 1;
4089 }
4090 #endif /* MBEDTLS_VERSION_NUMBER >= 0x03010000 */ /* mbedtls 3.01.0 */
4091 
4092 
4093 static int
4094 mod_mbedtls_ssl_conf_dhparameters(server *srv, plugin_config_socket *s, const buffer *dhparameters)
4095 {
4096     mbedtls_dhm_context dhm;
4097     mbedtls_dhm_init(&dhm);
4098     int rc = mbedtls_dhm_parse_dhmfile(&dhm, dhparameters->ptr);
4099     if (0 != rc)
4100         elogf(srv->errh, __FILE__,__LINE__, rc,
4101              "mbedtls_dhm_parse_dhmfile() %s", dhparameters->ptr);
4102     else {
4103         rc = mbedtls_ssl_conf_dh_param_ctx(s->ssl_ctx, &dhm);
4104         if (0 != rc)
4105             elogf(srv->errh, __FILE__,__LINE__, rc,
4106                  "mbedtls_ssl_conf_dh_param_ctx() %s", dhparameters->ptr);
4107     }
4108     mbedtls_dhm_free(&dhm);
4109     return (0 == rc);
4110 }
4111 
4112 
4113 #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.02.0 */
4114 static void
4115 mod_mbedtls_ssl_conf_proto (server *srv, plugin_config_socket *s, const buffer *b, int max)
4116 {
4117     int v = MBEDTLS_SSL_MINOR_VERSION_3; /* default: TLS v1.2 */
4118     if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */
4119       #ifdef MBEDTLS_SSL_MINOR_VERSION_4
4120         v = max ? MBEDTLS_SSL_MINOR_VERSION_4 : MBEDTLS_SSL_MINOR_VERSION_3;
4121       #else
4122         v = MBEDTLS_SSL_MINOR_VERSION_3;
4123       #endif
4124     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/
4125         v = max
4126           ?
4127            #ifdef MBEDTLS_SSL_MINOR_VERSION_4
4128             MBEDTLS_SSL_MINOR_VERSION_4  /* TLS v1.3 */
4129            #else
4130             MBEDTLS_SSL_MINOR_VERSION_3  /* TLS v1.2 */
4131            #endif
4132           :
4133            #if defined(MBEDTLS_SSL_MINOR_VERSION_1)
4134             MBEDTLS_SSL_MINOR_VERSION_1  /* TLS v1.0 */
4135            #elif defined(MBEDTLS_SSL_MINOR_VERSION_2)
4136             MBEDTLS_SSL_MINOR_VERSION_2  /* TLS v1.1 */
4137            #else
4138             MBEDTLS_SSL_MINOR_VERSION_3  /* TLS v1.2 */
4139            #endif
4140             ;
4141   #ifdef MBEDTLS_SSL_MINOR_VERSION_1
4142     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.0")))
4143         v = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS v1.0 */
4144   #endif
4145   #ifdef MBEDTLS_SSL_MINOR_VERSION_2
4146     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.1")))
4147         v = MBEDTLS_SSL_MINOR_VERSION_2; /* TLS v1.1 */
4148   #endif
4149   #ifdef MBEDTLS_SSL_MINOR_VERSION_3
4150     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2")))
4151         v = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS v1.2 */
4152   #endif
4153   #ifdef MBEDTLS_SSL_MINOR_VERSION_4
4154     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3")))
4155         v = MBEDTLS_SSL_MINOR_VERSION_4; /* TLS v1.3 */
4156   #endif
4157     else {
4158       #ifndef MBEDTLS_SSL_MINOR_VERSION_4
4159         if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3")))
4160             log_error(srv->errh, __FILE__, __LINE__,
4161                       "MTLS: ssl.openssl.ssl-conf-cmd %s TLSv1.3 not supported "
4162                       "by mod_mbedtls; using TLSv1.2",
4163                       max ? "MaxProtocol" : "MinProtocol");
4164         else
4165       #endif
4166         if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1"))
4167                  || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2"))) {
4168             log_error(srv->errh, __FILE__, __LINE__,
4169                       "MTLS: ssl.openssl.ssl-conf-cmd %s %s ignored",
4170                       max ? "MaxProtocol" : "MinProtocol", b->ptr);
4171             return;
4172         }
4173         else {
4174             log_error(srv->errh, __FILE__, __LINE__,
4175                       "MTLS: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored",
4176                       max ? "MaxProtocol" : "MinProtocol", b->ptr);
4177             return;
4178         }
4179     }
4180 
4181     max
4182       ? mbedtls_ssl_conf_max_version(s->ssl_ctx,MBEDTLS_SSL_MAJOR_VERSION_3,v)
4183       : mbedtls_ssl_conf_min_version(s->ssl_ctx,MBEDTLS_SSL_MAJOR_VERSION_3,v);
4184 }
4185 #else /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */ /* mbedtls 3.02.0 */
4186 static void
4187 mod_mbedtls_ssl_conf_proto (server *srv, plugin_config_socket *s, const buffer *b, int max)
4188 {
4189     int v = MBEDTLS_SSL_VERSION_TLS1_2; /* default: TLS v1.2 */
4190     if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */
4191         v = max ? MBEDTLS_SSL_VERSION_TLS1_3 : MBEDTLS_SSL_VERSION_TLS1_2;
4192     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/
4193         v = max ? MBEDTLS_SSL_VERSION_TLS1_3 : MBEDTLS_SSL_VERSION_TLS1_2;
4194     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2")))
4195         v = MBEDTLS_SSL_VERSION_TLS1_2;
4196     else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3")))
4197         v = MBEDTLS_SSL_VERSION_TLS1_3;
4198     else {
4199         if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1"))
4200             || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2"))) {
4201             log_error(srv->errh, __FILE__, __LINE__,
4202                       "MTLS: ssl.openssl.ssl-conf-cmd %s %s ignored",
4203                       max ? "MaxProtocol" : "MinProtocol", b->ptr);
4204             return;
4205         }
4206         else {
4207             log_error(srv->errh, __FILE__, __LINE__,
4208                       "MTLS: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored",
4209                       max ? "MaxProtocol" : "MinProtocol", b->ptr);
4210             return;
4211         }
4212     }
4213 
4214     max
4215       ? mbedtls_ssl_conf_max_tls_version(s->ssl_ctx, v)
4216       : mbedtls_ssl_conf_min_tls_version(s->ssl_ctx, v);
4217 }
4218 #endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */ /* mbedtls 3.02.0 */
4219 
4220 #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.00.0 */
4221 #ifdef MBEDTLS_SSL_SERVER_NAME_INDICATION
4222 #ifdef MBEDTLS_SSL_ALPN
4223 /*
4224  * XXX: forked from mbedtls
4225  *
4226  * ssl_parse_client_hello() is forked and modified from mbedtls
4227  *   library/ssl_srv.c:ssl_parse_client_hello()
4228  * due to limitations in mbedtls hooks.  Other than fetching input, ssl is not
4229  * modified here so that it can be reprocessed during handshake.
4230  *
4231  * It would be beneficial to have a callback after parsing client hello and all
4232  * extensions, and before certificate selection.  (SNI extension might occur
4233  * prior to ALPN extension, and a different certificate may be needed by
4234  * ALPN "acme-tls/1".)  Alternatively, mbedtls could provide an API to clear
4235  * &ssl->handshake->sni_key_cert, rather than forcing ssl_append_key_cert() with
4236  * no other option.
4237  */
4238 static int ssl_parse_client_hello( mbedtls_ssl_context *ssl, handler_ctx *hctx )
4239 {
4240     int ret;
4241     size_t msg_len;
4242     unsigned char *buf;
4243 
4244     /*
4245      * If renegotiating, then the input was read with mbedtls_ssl_read_record(),
4246      * otherwise read it ourselves manually in order to support SSLv2
4247      * ClientHello, which doesn't use the same record layer format.
4248      */
4249 #if defined(MBEDTLS_SSL_RENEGOTIATION)
4250     if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
4251 #endif
4252     {
4253         if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
4254         {
4255             /* No alert on a read error. */
4256             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
4257             return( ret );
4258         }
4259     }
4260 
4261     buf = ssl->in_hdr;
4262 
4263     /*
4264      * TLS Client Hello
4265      *
4266      * Record layer:
4267      *     0  .   0   message type
4268      *     1  .   2   protocol version
4269      *     3  .   11  DTLS: epoch + record sequence number
4270      *     3  .   4   message length
4271      */
4272     if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE )
4273     {
4274         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
4275     }
4276 
4277 #if defined(MBEDTLS_SSL_PROTO_DTLS)
4278     /*(not supported in lighttpd for now)*/
4279     /*(mbedtls_ssl_in_hdr_len() and mbedtls_ssl_hs_hdr_len() are in
4280      * mbedtls/ssl_internal.h but simple enough to repeat here) */
4281     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
4282         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
4283 #endif /* MBEDTLS_SSL_PROTO_DTLS */
4284 
4285     msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
4286 
4287 #if defined(MBEDTLS_SSL_RENEGOTIATION)
4288     if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
4289     {
4290         /* Set by mbedtls_ssl_read_record() */
4291         msg_len = ssl->in_hslen;
4292     }
4293     else
4294 #endif
4295     {
4296         if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
4297         {
4298             return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
4299         }
4300 
4301         if( ( ret = mbedtls_ssl_fetch_input( ssl,
4302                        5 /*mbedtls_ssl_in_hdr_len( ssl )*/ + msg_len ) ) != 0 )
4303         {
4304             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
4305             return( ret );
4306         }
4307     }
4308 
4309     buf = ssl->in_msg;
4310 
4311     /*
4312      * Handshake layer:
4313      *     0  .   0   handshake type
4314      *     1  .   3   handshake length
4315      *     4  .   5   DTLS only: message seqence number
4316      *     6  .   8   DTLS only: fragment offset
4317      *     9  .  11   DTLS only: fragment length
4318      */
4319     if( msg_len < 4 /*mbedtls_ssl_hs_hdr_len( ssl )*/ )
4320     {
4321         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4322     }
4323 
4324     if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
4325     {
4326         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
4327     }
4328 
4329     /* We don't support fragmentation of ClientHello (yet?) */
4330     if( buf[1] != 0 ||
4331         msg_len != 4u /*mbedtls_ssl_hs_hdr_len( ssl )*/ + ( ( buf[2] << 8 ) | buf[3] ) )
4332     {
4333         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4334     }
4335 
4336     buf += 4; /* mbedtls_ssl_hs_hdr_len( ssl ); */
4337     msg_len -= 4; /* mbedtls_ssl_hs_hdr_len( ssl ); */
4338 
4339     /*
4340      * ClientHello layer:
4341      *     0  .   1   protocol version
4342      *     2  .  33   random bytes (starting with 4 bytes of Unix time)
4343      *    34  .  35   session id length (1 byte)
4344      *    35  . 34+x  session id
4345      *   35+x . 35+x  DTLS only: cookie length (1 byte)
4346      *   36+x .  ..   DTLS only: cookie
4347      *    ..  .  ..   ciphersuite list length (2 bytes)
4348      *    ..  .  ..   ciphersuite list
4349      *    ..  .  ..   compression alg. list length (1 byte)
4350      *    ..  .  ..   compression alg. list
4351      *    ..  .  ..   extensions length (2 bytes, optional)
4352      *    ..  .  ..   extensions (optional)
4353      */
4354 
4355     /*
4356      * Minimal length (with everything empty and extensions omitted) is
4357      * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can
4358      * read at least up to session id length without worrying.
4359      */
4360     if( msg_len < 38 )
4361     {
4362         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4363     }
4364 
4365     /*
4366      * Check and save the protocol version
4367      */
4368     int major_ver, minor_ver;
4369     mbedtls_ssl_read_version( &major_ver, &minor_ver,
4370                       ssl->conf->transport, buf );
4371 
4372     /*
4373      * Check the session ID length and save session ID
4374      */
4375     const size_t sess_len = buf[34];
4376 
4377     if( sess_len > sizeof( ssl->session_negotiate->id ) ||
4378         sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */
4379     {
4380         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4381     }
4382 
4383     /*
4384      * Check the cookie length and content
4385      */
4386     const size_t ciph_offset = 35 + sess_len;
4387 
4388     const size_t ciph_len = ( buf[ciph_offset + 0] << 8 )
4389                           | ( buf[ciph_offset + 1]      );
4390 
4391     if( ciph_len < 2 ||
4392         ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */
4393         ( ciph_len % 2 ) != 0 )
4394     {
4395         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4396     }
4397 
4398     /*
4399      * Check the compression algorithms length and pick one
4400      */
4401     const size_t comp_offset = ciph_offset + 2 + ciph_len;
4402 
4403     const size_t comp_len = buf[comp_offset];
4404 
4405     if( comp_len < 1 ||
4406         comp_len > 16 ||
4407         comp_len + comp_offset + 1 > msg_len )
4408     {
4409         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4410     }
4411 
4412     /* Do not parse the extensions if the protocol is SSLv3 */
4413 #if defined(MBEDTLS_SSL_PROTO_SSL3)
4414     if( ( major_ver != 3 ) || ( minor_ver != 0 ) )
4415     {
4416 #endif
4417         /*
4418          * Check the extension length
4419          */
4420         const size_t ext_offset = comp_offset + 1 + comp_len;
4421         size_t ext_len;
4422         if( msg_len > ext_offset )
4423         {
4424             if( msg_len < ext_offset + 2 )
4425             {
4426                 return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4427             }
4428 
4429             ext_len = ( buf[ext_offset + 0] << 8 )
4430                     | ( buf[ext_offset + 1]      );
4431 
4432             if( msg_len != ext_offset + 2 + ext_len )
4433             {
4434                 return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4435             }
4436         }
4437         else
4438             ext_len = 0;
4439 
4440         unsigned char *ext = buf + ext_offset + 2;
4441 
4442         while( ext_len != 0 )
4443         {
4444             unsigned int ext_id;
4445             unsigned int ext_size;
4446             if ( ext_len < 4 ) {
4447                 return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4448             }
4449             ext_id   = ( ( ext[0] <<  8 ) | ( ext[1] ) );
4450             ext_size = ( ( ext[2] <<  8 ) | ( ext[3] ) );
4451 
4452             if( ext_size + 4 > ext_len )
4453             {
4454                 return( MBEDTLS_ERR_SSL_DECODE_ERROR );
4455             }
4456             switch( ext_id )
4457             {
4458 #if defined(MBEDTLS_SSL_ALPN)
4459             case MBEDTLS_TLS_EXT_ALPN:
4460                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
4461 
4462                 /*(lighttpd-specific)*/
4463                 ret = mod_mbedtls_alpn_select_cb(hctx, ext + 4, ext_size);
4464                 if( ret != 0 )
4465                     return( ret );
4466                 break;
4467 #endif /* MBEDTLS_SSL_ALPN */
4468 
4469             default:
4470                 break;
4471             }
4472 
4473             ext_len -= 4 + ext_size;
4474             ext += 4 + ext_size;
4475         }
4476 #if defined(MBEDTLS_SSL_PROTO_SSL3)
4477     }
4478 #endif
4479 
4480     return( 0 );
4481 }
4482 #endif /* MBEDTLS_SSL_ALPN */
4483 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
4484 #endif /* MBEDTLS_VERSION_NUMBER < 0x03000000 */ /* mbedtls 3.00.0 */
4485