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