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