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