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