1 //
2 // Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
3 // Copyright 2018 Capitar IT Group BV <info@capitar.com>
4 // Copyright 2019 Devolutions <info@devolutions.net>
5 //
6 // This software is supplied under the terms of the MIT License, a
7 // copy of which should be located in the distribution where this
8 // file was obtained (LICENSE.txt).  A copy of the license may also be
9 // found online at https://opensource.org/licenses/MIT.
10 //
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "core/nng_impl.h"
17 
18 #include <nng/supplemental/tls/engine.h>
19 #include <nng/supplemental/tls/tls.h>
20 
21 // NNG_TLS_MAX_SEND_SIZE limits the amount of data we will buffer for sending,
22 // exerting back-pressure if this size is exceeded.  The 16K is aligned to the
23 // maximum TLS record size.
24 #ifndef NNG_TLS_MAX_SEND_SIZE
25 #define NNG_TLS_MAX_SEND_SIZE 16384
26 #endif
27 
28 // NNG_TLS_MAX_RECV_SIZE limits the amount of data we will receive in a single
29 // operation.  As we have to buffer data, this drives the size of our
30 // intermediary buffer.  The 16K is aligned to the maximum TLS record size.
31 #ifndef NNG_TLX_MAX_RECV_SIZE
32 #define NNG_TLS_MAX_RECV_SIZE 16384
33 #endif
34 
35 // This file contains common code for TLS, and is only compiled if we
36 // have TLS configured in the system.  In particular, this provides the
37 // parts of TLS support that are invariant relative to different TLS
38 // libraries, such as dialer and listener support.
39 
40 #ifdef NNG_SUPP_TLS
41 
42 static const nng_tls_engine *tls_engine;
43 static nni_mtx               tls_engine_lock;
44 
45 struct nng_tls_config {
46 	nng_tls_engine_config_ops ops;
47 	const nng_tls_engine *    engine; // store this so we can verify
48 	nni_mtx                   lock;
49 	int                       ref;
50 	int                       busy;
51 	size_t                    size;
52 
53 	// ... engine config data follows
54 };
55 
56 typedef struct {
57 	nng_stream              stream;
58 	nng_tls_engine_conn_ops ops;
59 	nng_tls_config *        cfg;
60 	const nng_tls_engine *  engine;
61 	size_t                  size;
62 	nni_aio *               user_aio; // user's aio for connect/accept
63 	nni_aio                 conn_aio; // system aio for connect/accept
64 	nni_mtx                 lock;
65 	bool                    closed;
66 	bool                    hs_done;
67 	nni_list                send_queue;
68 	nni_list                recv_queue;
69 	nng_stream *            tcp;      // lower level stream
70 	nni_aio                 tcp_send; // lower level send pending
71 	nni_aio                 tcp_recv; // lower level recv pending
72 	uint8_t *               tcp_send_buf;
73 	uint8_t *               tcp_recv_buf;
74 	size_t                  tcp_recv_len;
75 	size_t                  tcp_recv_off;
76 	bool                    tcp_recv_pend;
77 	bool                    tcp_send_active;
78 	size_t                  tcp_send_len;
79 	size_t                  tcp_send_head;
80 	size_t                  tcp_send_tail;
81 	nni_reap_node           reap;
82 
83 	// ... engine connection data follows
84 } tls_conn;
85 
86 static void tls_tcp_send_cb(void *arg);
87 static void tls_tcp_recv_cb(void *arg);
88 static void tls_do_send(tls_conn *);
89 static void tls_do_recv(tls_conn *);
90 static void tls_tcp_send_start(tls_conn *);
91 static void tls_free(void *);
92 static void tls_reap(void *);
93 static int  tls_alloc(tls_conn **, nng_tls_config *, nng_aio *);
94 static int  tls_start(tls_conn *, nng_stream *);
95 static void tls_tcp_error(tls_conn *, int);
96 
97 static nni_reap_list tls_conn_reap_list = {
98 	.rl_offset = offsetof(tls_conn, reap),
99 	.rl_func   = tls_reap,
100 };
101 
102 typedef struct {
103 	nng_stream_dialer  ops;
104 	nng_stream_dialer *d; // underlying TCP dialer
105 	nng_tls_config *   cfg;
106 	nni_mtx            lk; // protects the config
107 } tls_dialer;
108 
109 static void
tls_dialer_close(void * arg)110 tls_dialer_close(void *arg)
111 {
112 	tls_dialer *d = arg;
113 	nng_stream_dialer_close(d->d);
114 }
115 
116 static void
tls_dialer_free(void * arg)117 tls_dialer_free(void *arg)
118 {
119 	tls_dialer *d;
120 	if ((d = arg) != NULL) {
121 		nng_stream_dialer_free(d->d);
122 		nng_tls_config_free(d->cfg);
123 		nni_mtx_fini(&d->lk);
124 		NNI_FREE_STRUCT(d);
125 	}
126 }
127 
128 // For dialing, we need to have our own completion callback, instead of
129 // the user's completion callback.
130 
131 static void
tls_conn_cb(void * arg)132 tls_conn_cb(void *arg)
133 {
134 	tls_conn *  conn = arg;
135 	nng_stream *tcp;
136 	int         rv;
137 
138 	if ((rv = nni_aio_result(&conn->conn_aio)) != 0) {
139 		nni_aio_finish_error(conn->user_aio, rv);
140 		nng_stream_free(&conn->stream);
141 		return;
142 	}
143 
144 	tcp = nni_aio_get_output(&conn->conn_aio, 0);
145 
146 	if ((rv = tls_start(conn, tcp)) != 0) {
147 		nni_aio_finish_error(conn->user_aio, rv);
148 		nng_stream_free(&conn->stream);
149 		return;
150 	}
151 
152 	nni_aio_set_output(conn->user_aio, 0, &conn->stream);
153 	nni_aio_finish(conn->user_aio, 0, 0);
154 }
155 
156 // Dialer cancel is called when the user has indicated that they no longer
157 // want to wait for the connection to establish.
158 static void
tls_conn_cancel(nni_aio * aio,void * arg,int rv)159 tls_conn_cancel(nni_aio *aio, void *arg, int rv)
160 {
161 	tls_conn *conn = arg;
162 
163 	NNI_ARG_UNUSED(aio);
164 
165 	// Just pass this down.  If the connection is already done, this
166 	// will have no effect.
167 	nni_aio_abort(&conn->conn_aio, rv);
168 }
169 
170 static void
tls_dialer_dial(void * arg,nng_aio * aio)171 tls_dialer_dial(void *arg, nng_aio *aio)
172 {
173 	tls_dialer *d = arg;
174 	int         rv;
175 	tls_conn *  conn;
176 
177 	if (nni_aio_begin(aio) != 0) {
178 		return;
179 	}
180 	if ((rv = tls_alloc(&conn, d->cfg, aio)) != 0) {
181 		nni_aio_finish_error(aio, rv);
182 		return;
183 	}
184 
185 	if ((rv = nni_aio_schedule(aio, tls_conn_cancel, conn)) != 0) {
186 		nni_aio_finish_error(aio, rv);
187 		tls_free(conn);
188 		return;
189 	}
190 
191 	nng_stream_dialer_dial(d->d, &conn->conn_aio);
192 }
193 
194 static int
tls_check_string(const void * v,size_t sz,nni_opt_type t)195 tls_check_string(const void *v, size_t sz, nni_opt_type t)
196 {
197 	switch (t) {
198 	case NNI_TYPE_OPAQUE:
199 		if (nni_strnlen(v, sz) >= sz) {
200 			return (NNG_EINVAL);
201 		}
202 		return (0);
203 	case NNI_TYPE_STRING:
204 		// Caller is assumed to pass a good string.
205 		return (0);
206 	default:
207 		return (NNG_EBADTYPE);
208 	}
209 }
210 
211 static int
tls_dialer_set_config(void * arg,const void * buf,size_t sz,nni_type t)212 tls_dialer_set_config(void *arg, const void *buf, size_t sz, nni_type t)
213 {
214 	int             rv;
215 	nng_tls_config *cfg;
216 	tls_dialer *    d = arg;
217 	nng_tls_config *old;
218 
219 	if ((rv = nni_copyin_ptr((void **) &cfg, buf, sz, t)) != 0) {
220 		return (rv);
221 	}
222 	if (cfg == NULL) {
223 		return (NNG_EINVAL);
224 	}
225 	nng_tls_config_hold(cfg);
226 
227 	nni_mtx_lock(&d->lk);
228 	old    = d->cfg;
229 	d->cfg = cfg;
230 	nni_mtx_unlock(&d->lk);
231 
232 	nng_tls_config_free(old);
233 	return (0);
234 }
235 
236 static int
tls_dialer_get_config(void * arg,void * buf,size_t * szp,nni_type t)237 tls_dialer_get_config(void *arg, void *buf, size_t *szp, nni_type t)
238 {
239 	tls_dialer *    d = arg;
240 	nng_tls_config *cfg;
241 	int             rv;
242 	nni_mtx_lock(&d->lk);
243 	if ((cfg = d->cfg) != NULL) {
244 		nng_tls_config_hold(cfg);
245 	}
246 	if ((rv = nni_copyout_ptr(cfg, buf, szp, t)) != 0) {
247 		nng_tls_config_free(cfg);
248 	}
249 	nni_mtx_unlock(&d->lk);
250 	return (rv);
251 }
252 
253 static int
tls_dialer_set_server_name(void * arg,const void * buf,size_t sz,nni_type t)254 tls_dialer_set_server_name(void *arg, const void *buf, size_t sz, nni_type t)
255 {
256 	tls_dialer *d = arg;
257 	int         rv;
258 	if ((rv = tls_check_string(buf, sz, t)) == 0) {
259 		nni_mtx_lock(&d->lk);
260 		rv = nng_tls_config_server_name(d->cfg, buf);
261 		nni_mtx_unlock(&d->lk);
262 	}
263 	return (rv);
264 }
265 
266 static int
tls_dialer_set_auth_mode(void * arg,const void * buf,size_t sz,nni_type t)267 tls_dialer_set_auth_mode(void *arg, const void *buf, size_t sz, nni_type t)
268 {
269 	int         mode;
270 	int         rv;
271 	tls_dialer *d = arg;
272 
273 	rv = nni_copyin_int(&mode, buf, sz, NNG_TLS_AUTH_MODE_NONE,
274 	    NNG_TLS_AUTH_MODE_REQUIRED, t);
275 	if (rv == 0) {
276 		nni_mtx_lock(&d->lk);
277 		rv = nng_tls_config_auth_mode(d->cfg, mode);
278 		nni_mtx_unlock(&d->lk);
279 	}
280 	return (rv);
281 }
282 
283 static int
tls_dialer_set_ca_file(void * arg,const void * buf,size_t sz,nni_opt_type t)284 tls_dialer_set_ca_file(void *arg, const void *buf, size_t sz, nni_opt_type t)
285 {
286 	tls_dialer *d = arg;
287 	int         rv;
288 
289 	if ((rv = tls_check_string(buf, sz, t)) == 0) {
290 		nni_mtx_lock(&d->lk);
291 		rv = nng_tls_config_ca_file(d->cfg, buf);
292 		nni_mtx_unlock(&d->lk);
293 	}
294 	return (rv);
295 }
296 
297 static int
tls_dialer_set_cert_key_file(void * arg,const void * buf,size_t sz,nni_opt_type t)298 tls_dialer_set_cert_key_file(
299     void *arg, const void *buf, size_t sz, nni_opt_type t)
300 {
301 	tls_dialer *d = arg;
302 	int         rv;
303 
304 	if ((rv = tls_check_string(buf, sz, t)) == 0) {
305 		nni_mtx_lock(&d->lk);
306 		rv = nng_tls_config_cert_key_file(d->cfg, buf, NULL);
307 		nni_mtx_unlock(&d->lk);
308 	}
309 	return (rv);
310 }
311 
312 static const nni_option tls_dialer_opts[] = {
313 	{
314 	    .o_name = NNG_OPT_TLS_CONFIG,
315 	    .o_get  = tls_dialer_get_config,
316 	    .o_set  = tls_dialer_set_config,
317 	},
318 	{
319 	    .o_name = NNG_OPT_TLS_SERVER_NAME,
320 	    .o_set  = tls_dialer_set_server_name,
321 	},
322 	{
323 	    .o_name = NNG_OPT_TLS_CA_FILE,
324 	    .o_set  = tls_dialer_set_ca_file,
325 	},
326 	{
327 	    .o_name = NNG_OPT_TLS_CERT_KEY_FILE,
328 	    .o_set  = tls_dialer_set_cert_key_file,
329 	},
330 	{
331 	    .o_name = NNG_OPT_TLS_AUTH_MODE,
332 	    .o_set  = tls_dialer_set_auth_mode,
333 	},
334 	{
335 	    .o_name = NULL,
336 	},
337 };
338 
339 static int
tls_dialer_get(void * arg,const char * name,void * buf,size_t * szp,nni_type t)340 tls_dialer_get(void *arg, const char *name, void *buf, size_t *szp, nni_type t)
341 {
342 	tls_dialer *d = arg;
343 	int         rv;
344 
345 	rv = nni_stream_dialer_get(d->d, name, buf, szp, t);
346 	if (rv == NNG_ENOTSUP) {
347 		rv = nni_getopt(tls_dialer_opts, name, d, buf, szp, t);
348 	}
349 	return (rv);
350 }
351 
352 static int
tls_dialer_set(void * arg,const char * name,const void * buf,size_t sz,nni_type t)353 tls_dialer_set(
354     void *arg, const char *name, const void *buf, size_t sz, nni_type t)
355 {
356 	tls_dialer *d = arg;
357 	int         rv;
358 
359 	rv = nni_stream_dialer_set(d->d, name, buf, sz, t);
360 	if (rv == NNG_ENOTSUP) {
361 		rv = nni_setopt(tls_dialer_opts, name, d, buf, sz, t);
362 	}
363 	return (rv);
364 }
365 
366 int
nni_tls_dialer_alloc(nng_stream_dialer ** dp,const nng_url * url)367 nni_tls_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)
368 {
369 	tls_dialer *d;
370 	int         rv;
371 	nng_url     my_url;
372 
373 	memcpy(&my_url, url, sizeof(my_url));
374 	if (strncmp(my_url.u_scheme, "tls+", 4) == 0) {
375 		my_url.u_scheme += 4;
376 	}
377 
378 	if ((rv = nni_init()) != 0) {
379 		return (rv);
380 	}
381 	if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
382 		return (NNG_ENOMEM);
383 	}
384 	nni_mtx_init(&d->lk);
385 
386 	if ((rv = nng_stream_dialer_alloc_url(&d->d, &my_url)) != 0) {
387 		nni_mtx_fini(&d->lk);
388 		NNI_FREE_STRUCT(d);
389 		return (rv);
390 	}
391 	if ((rv = nng_tls_config_alloc(&d->cfg, NNG_TLS_MODE_CLIENT)) != 0) {
392 		nng_stream_dialer_free(d->d);
393 		nni_mtx_fini(&d->lk);
394 		NNI_FREE_STRUCT(d);
395 		return (rv);
396 	}
397 
398 	// Set the expected outbound hostname
399 	nng_tls_config_server_name(d->cfg, url->u_hostname);
400 
401 	d->ops.sd_close = tls_dialer_close;
402 	d->ops.sd_free  = tls_dialer_free;
403 	d->ops.sd_dial  = tls_dialer_dial;
404 	d->ops.sd_get   = tls_dialer_get;
405 	d->ops.sd_set   = tls_dialer_set;
406 	*dp             = (void *) d;
407 	return (rv);
408 }
409 
410 typedef struct {
411 	nng_stream_listener  ops;
412 	nng_stream_listener *l;
413 	nng_tls_config *     cfg;
414 	nni_mtx              lk;
415 } tls_listener;
416 
417 static void
tls_listener_close(void * arg)418 tls_listener_close(void *arg)
419 {
420 	tls_listener *l = arg;
421 	nng_stream_listener_close(l->l);
422 }
423 
424 static void
tls_listener_free(void * arg)425 tls_listener_free(void *arg)
426 {
427 	tls_listener *l;
428 	if ((l = arg) != NULL) {
429 		tls_listener_close(l);
430 		nng_tls_config_free(l->cfg);
431 		nng_stream_listener_free(l->l);
432 		nni_mtx_fini(&l->lk);
433 		NNI_FREE_STRUCT(l);
434 	}
435 }
436 
437 static int
tls_listener_listen(void * arg)438 tls_listener_listen(void *arg)
439 {
440 	tls_listener *l = arg;
441 	return (nng_stream_listener_listen(l->l));
442 }
443 
444 static void
tls_listener_accept(void * arg,nng_aio * aio)445 tls_listener_accept(void *arg, nng_aio *aio)
446 {
447 	tls_listener *l = arg;
448 	int           rv;
449 	tls_conn *    conn;
450 
451 	if (nni_aio_begin(aio) != 0) {
452 		return;
453 	}
454 	if ((rv = tls_alloc(&conn, l->cfg, aio)) != 0) {
455 		nni_aio_finish_error(aio, rv);
456 		return;
457 	}
458 
459 	if ((rv = nni_aio_schedule(aio, tls_conn_cancel, conn)) != 0) {
460 		nni_aio_finish_error(aio, rv);
461 		tls_free(conn);
462 		return;
463 	}
464 
465 	nng_stream_listener_accept(l->l, &conn->conn_aio);
466 }
467 
468 static int
tls_listener_set_config(void * arg,const void * buf,size_t sz,nni_type t)469 tls_listener_set_config(void *arg, const void *buf, size_t sz, nni_type t)
470 {
471 	int             rv;
472 	nng_tls_config *cfg;
473 	tls_listener *  l = arg;
474 	nng_tls_config *old;
475 
476 	if ((rv = nni_copyin_ptr((void **) &cfg, buf, sz, t)) != 0) {
477 		return (rv);
478 	}
479 	if (cfg == NULL) {
480 		return (NNG_EINVAL);
481 	}
482 
483 	nng_tls_config_hold(cfg);
484 
485 	nni_mtx_lock(&l->lk);
486 	old    = l->cfg;
487 	l->cfg = cfg;
488 	nni_mtx_unlock(&l->lk);
489 
490 	nng_tls_config_free(old);
491 
492 	return (0);
493 }
494 
495 static int
tls_listener_get_config(void * arg,void * buf,size_t * szp,nni_type t)496 tls_listener_get_config(void *arg, void *buf, size_t *szp, nni_type t)
497 {
498 	tls_listener *  l = arg;
499 	nng_tls_config *cfg;
500 	int             rv;
501 	nni_mtx_lock(&l->lk);
502 	if ((cfg = l->cfg) != NULL) {
503 		nng_tls_config_hold(cfg);
504 	}
505 	if ((rv = nni_copyout_ptr(cfg, buf, szp, t)) != 0) {
506 		nng_tls_config_free(cfg);
507 	}
508 	nni_mtx_unlock(&l->lk);
509 	return (rv);
510 }
511 
512 static int
tls_listener_set_server_name(void * arg,const void * buf,size_t sz,nni_type t)513 tls_listener_set_server_name(void *arg, const void *buf, size_t sz, nni_type t)
514 {
515 	tls_listener *l = arg;
516 	int           rv;
517 	if ((rv = tls_check_string(buf, sz, t)) == 0) {
518 		nni_mtx_lock(&l->lk);
519 		rv = nng_tls_config_server_name(l->cfg, buf);
520 		nni_mtx_unlock(&l->lk);
521 	}
522 	return (rv);
523 }
524 
525 static int
tls_listener_set_auth_mode(void * arg,const void * buf,size_t sz,nni_type t)526 tls_listener_set_auth_mode(void *arg, const void *buf, size_t sz, nni_type t)
527 {
528 	int           mode;
529 	int           rv;
530 	tls_listener *l = arg;
531 
532 	rv = nni_copyin_int(&mode, buf, sz, NNG_TLS_AUTH_MODE_NONE,
533 	    NNG_TLS_AUTH_MODE_REQUIRED, t);
534 	if (rv == 0) {
535 		nni_mtx_lock(&l->lk);
536 		rv = nng_tls_config_auth_mode(l->cfg, mode);
537 		nni_mtx_unlock(&l->lk);
538 	}
539 	return (rv);
540 }
541 
542 static int
tls_listener_set_ca_file(void * arg,const void * buf,size_t sz,nni_opt_type t)543 tls_listener_set_ca_file(void *arg, const void *buf, size_t sz, nni_opt_type t)
544 {
545 	tls_listener *l = arg;
546 	int           rv;
547 
548 	if ((rv = tls_check_string(buf, sz, t)) == 0) {
549 		nni_mtx_lock(&l->lk);
550 		rv = nng_tls_config_ca_file(l->cfg, buf);
551 		nni_mtx_unlock(&l->lk);
552 	}
553 	return (rv);
554 }
555 
556 static int
tls_listener_set_cert_key_file(void * arg,const void * buf,size_t sz,nni_opt_type t)557 tls_listener_set_cert_key_file(
558     void *arg, const void *buf, size_t sz, nni_opt_type t)
559 {
560 	tls_listener *l = arg;
561 	int           rv;
562 
563 	if ((rv = tls_check_string(buf, sz, t)) == 0) {
564 		nni_mtx_lock(&l->lk);
565 		rv = nng_tls_config_cert_key_file(l->cfg, buf, NULL);
566 		nni_mtx_unlock(&l->lk);
567 	}
568 	return (rv);
569 }
570 
571 static const nni_option tls_listener_opts[] = {
572 	{
573 	    .o_name = NNG_OPT_TLS_CONFIG,
574 	    .o_get  = tls_listener_get_config,
575 	    .o_set  = tls_listener_set_config,
576 	},
577 	{
578 	    .o_name = NNG_OPT_TLS_SERVER_NAME,
579 	    .o_set  = tls_listener_set_server_name,
580 	},
581 	{
582 	    .o_name = NNG_OPT_TLS_CA_FILE,
583 	    .o_set  = tls_listener_set_ca_file,
584 	},
585 	{
586 	    .o_name = NNG_OPT_TLS_CERT_KEY_FILE,
587 	    .o_set  = tls_listener_set_cert_key_file,
588 	},
589 	{
590 	    .o_name = NNG_OPT_TLS_AUTH_MODE,
591 	    .o_set  = tls_listener_set_auth_mode,
592 	},
593 	{
594 	    .o_name = NULL,
595 	},
596 };
597 
598 static int
tls_listener_get(void * arg,const char * name,void * buf,size_t * szp,nni_type t)599 tls_listener_get(
600     void *arg, const char *name, void *buf, size_t *szp, nni_type t)
601 {
602 	int           rv;
603 	tls_listener *l = arg;
604 
605 	rv = nni_stream_listener_get(l->l, name, buf, szp, t);
606 	if (rv == NNG_ENOTSUP) {
607 		rv = nni_getopt(tls_listener_opts, name, l, buf, szp, t);
608 	}
609 	return (rv);
610 }
611 
612 static int
tls_listener_set(void * arg,const char * name,const void * buf,size_t sz,nni_type t)613 tls_listener_set(
614     void *arg, const char *name, const void *buf, size_t sz, nni_type t)
615 {
616 	int           rv;
617 	tls_listener *l = arg;
618 
619 	rv = nni_stream_listener_set(l->l, name, buf, sz, t);
620 	if (rv == NNG_ENOTSUP) {
621 		rv = nni_setopt(tls_listener_opts, name, l, buf, sz, t);
622 	}
623 	return (rv);
624 }
625 
626 int
nni_tls_listener_alloc(nng_stream_listener ** lp,const nng_url * url)627 nni_tls_listener_alloc(nng_stream_listener **lp, const nng_url *url)
628 {
629 	tls_listener *l;
630 	int           rv;
631 	nng_url       my_url;
632 
633 	memcpy(&my_url, url, sizeof(my_url));
634 
635 	if (strncmp(my_url.u_scheme, "tls+", 4) == 0) {
636 		my_url.u_scheme += 4;
637 	}
638 
639 	if ((rv = nni_init()) != 0) {
640 		return (rv);
641 	}
642 	if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
643 		return (NNG_ENOMEM);
644 	}
645 	nni_mtx_init(&l->lk);
646 
647 	if ((rv = nng_stream_listener_alloc_url(&l->l, &my_url)) != 0) {
648 		nni_mtx_fini(&l->lk);
649 		NNI_FREE_STRUCT(l);
650 		return (rv);
651 	}
652 	if ((rv = nng_tls_config_alloc(&l->cfg, NNG_TLS_MODE_SERVER)) != 0) {
653 		nng_stream_listener_free(l->l);
654 		nni_mtx_fini(&l->lk);
655 		NNI_FREE_STRUCT(l);
656 		return (rv);
657 	}
658 	l->ops.sl_free   = tls_listener_free;
659 	l->ops.sl_close  = tls_listener_close;
660 	l->ops.sl_accept = tls_listener_accept;
661 	l->ops.sl_listen = tls_listener_listen;
662 	l->ops.sl_get    = tls_listener_get;
663 	l->ops.sl_set    = tls_listener_set;
664 	*lp              = (void *) l;
665 	return (0);
666 }
667 
668 static void
tls_cancel(nni_aio * aio,void * arg,int rv)669 tls_cancel(nni_aio *aio, void *arg, int rv)
670 {
671 	tls_conn *conn = arg;
672 	nni_mtx_lock(&conn->lock);
673 	if (aio == nni_list_first(&conn->recv_queue)) {
674 		nni_aio_abort(&conn->tcp_recv, rv);
675 	} else if (aio == nni_list_first(&conn->send_queue)) {
676 		nni_aio_abort(&conn->tcp_send, rv);
677 	} else if (nni_aio_list_active(aio)) {
678 		nni_aio_list_remove(aio);
679 		nni_aio_finish_error(aio, rv);
680 	}
681 	nni_mtx_unlock(&conn->lock);
682 }
683 
684 // tls_send implements the upper layer stream send operation.
685 static void
tls_send(void * arg,nni_aio * aio)686 tls_send(void *arg, nni_aio *aio)
687 {
688 	int       rv;
689 	tls_conn *conn = arg;
690 
691 	if (nni_aio_begin(aio) != 0) {
692 		return;
693 	}
694 	nni_mtx_lock(&conn->lock);
695 	if (conn->closed) {
696 		nni_mtx_unlock(&conn->lock);
697 		nni_aio_finish_error(aio, NNG_ECLOSED);
698 		return;
699 	}
700 	if ((rv = nni_aio_schedule(aio, tls_cancel, conn)) != 0) {
701 		nni_mtx_unlock(&conn->lock);
702 		nni_aio_finish_error(aio, rv);
703 		return;
704 	}
705 	nni_list_append(&conn->send_queue, aio);
706 	tls_do_send(conn);
707 	nni_mtx_unlock(&conn->lock);
708 }
709 
710 static void
tls_recv(void * arg,nni_aio * aio)711 tls_recv(void *arg, nni_aio *aio)
712 {
713 	int       rv;
714 	tls_conn *conn = arg;
715 
716 	if (nni_aio_begin(aio) != 0) {
717 		return;
718 	}
719 	nni_mtx_lock(&conn->lock);
720 	if (conn->closed) {
721 		nni_mtx_unlock(&conn->lock);
722 		nni_aio_finish_error(aio, NNG_ECLOSED);
723 		return;
724 	}
725 	if ((rv = nni_aio_schedule(aio, tls_cancel, conn)) != 0) {
726 		nni_mtx_unlock(&conn->lock);
727 		nni_aio_finish_error(aio, rv);
728 		return;
729 	}
730 
731 	nni_list_append(&conn->recv_queue, aio);
732 	tls_do_recv(conn);
733 	nni_mtx_unlock(&conn->lock);
734 }
735 
736 static void
tls_close(void * arg)737 tls_close(void *arg)
738 {
739 	tls_conn *conn = arg;
740 
741 	nni_mtx_lock(&conn->lock);
742 	conn->ops.close((void *) (conn + 1));
743 	tls_tcp_error(conn, NNG_ECLOSED);
744 	nni_mtx_unlock(&conn->lock);
745 	nng_stream_close(conn->tcp);
746 }
747 
748 static int
tls_get_verified(void * arg,void * buf,size_t * szp,nni_type t)749 tls_get_verified(void *arg, void *buf, size_t *szp, nni_type t)
750 {
751 	tls_conn *conn = arg;
752 	bool      v;
753 
754 	nni_mtx_lock(&conn->lock);
755 	v = conn->ops.verified((void *) (conn + 1));
756 	nni_mtx_unlock(&conn->lock);
757 	return (nni_copyout_bool(v, buf, szp, t));
758 }
759 
760 static const nni_option tls_options[] = {
761 	{
762 	    .o_name = NNG_OPT_TLS_VERIFIED,
763 	    .o_get  = tls_get_verified,
764 	},
765 	{
766 	    .o_name = NULL,
767 	},
768 };
769 
770 static int
tls_set(void * arg,const char * name,const void * buf,size_t sz,nni_type t)771 tls_set(void *arg, const char *name, const void *buf, size_t sz, nni_type t)
772 {
773 	tls_conn *  conn = arg;
774 	int         rv;
775 	nng_stream *tcp;
776 
777 	tcp = (conn != NULL) ? conn->tcp : NULL;
778 
779 	if ((rv = nni_stream_set(tcp, name, buf, sz, t)) != NNG_ENOTSUP) {
780 		return (rv);
781 	}
782 	return (nni_setopt(tls_options, name, conn, buf, sz, t));
783 }
784 
785 static int
tls_get(void * arg,const char * name,void * buf,size_t * szp,nni_type t)786 tls_get(void *arg, const char *name, void *buf, size_t *szp, nni_type t)
787 {
788 	tls_conn *conn = arg;
789 	int       rv;
790 
791 	if ((rv = nni_stream_get(conn->tcp, name, buf, szp, t)) !=
792 	    NNG_ENOTSUP) {
793 		return (rv);
794 	}
795 	return (nni_getopt(tls_options, name, conn, buf, szp, t));
796 }
797 
798 static int
tls_alloc(tls_conn ** conn_p,nng_tls_config * cfg,nng_aio * user_aio)799 tls_alloc(tls_conn **conn_p, nng_tls_config *cfg, nng_aio *user_aio)
800 {
801 	tls_conn *            conn;
802 	const nng_tls_engine *eng;
803 	size_t                size;
804 
805 	eng = cfg->engine;
806 
807 	size = NNI_ALIGN_UP(sizeof(*conn)) + eng->conn_ops->size;
808 
809 	if ((conn = nni_zalloc(size)) == NULL) {
810 		return (NNG_ENOMEM);
811 	}
812 	if (((conn->tcp_send_buf = nni_alloc(NNG_TLS_MAX_SEND_SIZE)) ==
813 	        NULL) ||
814 	    ((conn->tcp_recv_buf = nni_alloc(NNG_TLS_MAX_RECV_SIZE)) ==
815 	        NULL)) {
816 		tls_free(conn);
817 		return (NNG_ENOMEM);
818 	}
819 	conn->size     = size;
820 	conn->ops      = *eng->conn_ops;
821 	conn->engine   = eng;
822 	conn->user_aio = user_aio;
823 	conn->cfg      = cfg;
824 
825 	nni_aio_init(&conn->conn_aio, tls_conn_cb, conn);
826 	nni_aio_init(&conn->tcp_recv, tls_tcp_recv_cb, conn);
827 	nni_aio_init(&conn->tcp_send, tls_tcp_send_cb, conn);
828 	nni_aio_list_init(&conn->send_queue);
829 	nni_aio_list_init(&conn->recv_queue);
830 	nni_mtx_init(&conn->lock);
831 	nni_aio_set_timeout(&conn->tcp_send, NNG_DURATION_INFINITE);
832 	nni_aio_set_timeout(&conn->tcp_recv, NNG_DURATION_INFINITE);
833 
834 	conn->stream.s_close = tls_close;
835 	conn->stream.s_free  = tls_free;
836 	conn->stream.s_send  = tls_send;
837 	conn->stream.s_recv  = tls_recv;
838 	conn->stream.s_get   = tls_get;
839 	conn->stream.s_set   = tls_set;
840 
841 	nng_tls_config_hold(cfg);
842 	*conn_p = conn;
843 	return (0);
844 }
845 
846 static void
tls_reap(void * arg)847 tls_reap(void *arg)
848 {
849 	tls_conn *conn = arg;
850 
851 	// Shut it all down first.  We should be freed.
852 	if (conn->tcp != NULL) {
853 		nng_stream_close(conn->tcp);
854 	}
855 	nni_aio_stop(&conn->conn_aio);
856 	nni_aio_stop(&conn->tcp_send);
857 	nni_aio_stop(&conn->tcp_recv);
858 
859 	conn->ops.fini((void *) (conn + 1));
860 	nni_aio_fini(&conn->conn_aio);
861 	nni_aio_fini(&conn->tcp_send);
862 	nni_aio_fini(&conn->tcp_recv);
863 	nng_stream_free(conn->tcp);
864 	if (conn->cfg != NULL) {
865 		nng_tls_config_free(conn->cfg); // this drops our hold on it
866 	}
867 	if (conn->tcp_send_buf != NULL) {
868 		nni_free(conn->tcp_send_buf, NNG_TLS_MAX_SEND_SIZE);
869 	}
870 	if (conn->tcp_recv_buf != NULL) {
871 		nni_free(conn->tcp_recv_buf, NNG_TLS_MAX_RECV_SIZE);
872 	}
873 	NNI_FREE_STRUCT(conn);
874 }
875 
876 static void
tls_free(void * arg)877 tls_free(void *arg)
878 {
879 	tls_conn *conn = arg;
880 
881 	nni_reap(&tls_conn_reap_list, conn);
882 }
883 
884 static int
tls_start(tls_conn * conn,nng_stream * tcp)885 tls_start(tls_conn *conn, nng_stream *tcp)
886 {
887 	int rv;
888 
889 	conn->tcp = tcp;
890 	rv        = conn->ops.init(
891             (void *) (conn + 1), conn, (void *) (conn->cfg + 1));
892 	return (rv);
893 }
894 
895 static void
tls_tcp_error(tls_conn * conn,int rv)896 tls_tcp_error(tls_conn *conn, int rv)
897 {
898 	// An error here is fatal.  Shut it all down.
899 	nni_aio *aio;
900 	nng_stream_close(conn->tcp);
901 	nni_aio_close(&conn->tcp_send);
902 	nni_aio_close(&conn->tcp_recv);
903 	while (((aio = nni_list_first(&conn->send_queue)) != NULL) ||
904 	    ((aio = nni_list_first(&conn->recv_queue)) != NULL)) {
905 		nni_aio_list_remove(aio);
906 		nni_aio_finish_error(aio, rv);
907 	}
908 }
909 
910 static bool
tls_do_handshake(tls_conn * conn)911 tls_do_handshake(tls_conn *conn)
912 {
913 	int rv;
914 	if (conn->hs_done) {
915 		return (true);
916 	}
917 	rv = conn->ops.handshake((void *) (conn + 1));
918 	if (rv == NNG_EAGAIN) {
919 		// We need more data.
920 		return (false);
921 	}
922 	if (rv == 0) {
923 		conn->hs_done = true;
924 		return (true);
925 	}
926 	tls_tcp_error(conn, rv);
927 	return (true);
928 }
929 
930 static void
tls_do_recv(tls_conn * conn)931 tls_do_recv(tls_conn *conn)
932 {
933 	nni_aio *aio;
934 
935 	while ((aio = nni_list_first(&conn->recv_queue)) != NULL) {
936 		uint8_t *buf = NULL;
937 		size_t   len = 0;
938 		nni_iov *iov;
939 		unsigned nio;
940 		int      rv;
941 
942 		nni_aio_get_iov(aio, &nio, &iov);
943 
944 		for (unsigned i = 0; i < nio; i++) {
945 			if (iov[i].iov_len != 0) {
946 				buf = iov[i].iov_buf;
947 				len = iov[i].iov_len;
948 				break;
949 			}
950 		}
951 		if (len == 0 || buf == NULL) {
952 			// Caller has asked to receive "nothing".
953 			nni_aio_list_remove(aio);
954 			nni_aio_finish_error(aio, NNG_EINVAL);
955 			continue;
956 		}
957 
958 		rv = conn->ops.recv((void *) (conn + 1), buf, &len);
959 		if (rv == NNG_EAGAIN) {
960 			// Nothing more we can do, the engine doesn't
961 			// have anything else for us (yet).
962 			return;
963 		}
964 
965 		// Unlike the send side, we want to return back to the
966 		// caller as *soon* as we have some data.
967 		nni_aio_list_remove(aio);
968 
969 		if (rv != 0) {
970 			nni_aio_finish_error(aio, rv);
971 		} else {
972 			nni_aio_finish(aio, 0, len);
973 		}
974 	}
975 }
976 
977 // tls_do_send attempts to send user data.
978 static void
tls_do_send(tls_conn * conn)979 tls_do_send(tls_conn *conn)
980 {
981 	nni_aio *aio;
982 
983 	while ((aio = nni_list_first(&conn->send_queue)) != NULL) {
984 		uint8_t *buf = NULL;
985 		size_t   len = 0;
986 		nni_iov *iov;
987 		unsigned nio;
988 		int      rv;
989 
990 		nni_aio_get_iov(aio, &nio, &iov);
991 
992 		for (unsigned i = 0; i < nio; i++) {
993 			if (iov[i].iov_len != 0) {
994 				buf = iov[i].iov_buf;
995 				len = iov[i].iov_len;
996 				break;
997 			}
998 		}
999 		if (len == 0 || buf == NULL) {
1000 			nni_aio_list_remove(aio);
1001 			// Presumably this means we've completed this
1002 			// one, lets preserve the count, and move to the
1003 			// next.
1004 			nni_aio_finish(aio, 0, nni_aio_count(aio));
1005 			continue;
1006 		}
1007 
1008 		// Ask the engine to send.
1009 		rv = conn->ops.send((void *) (conn + 1), buf, &len);
1010 		if (rv == NNG_EAGAIN) {
1011 			// Can't send any more, wait for callback.
1012 			return;
1013 		}
1014 
1015 		if (rv != 0) {
1016 			nni_aio_list_remove(aio);
1017 			nni_aio_finish_error(aio, rv);
1018 		} else {
1019 			nni_aio_list_remove(aio);
1020 			nni_aio_finish(aio, 0, len);
1021 		}
1022 	}
1023 }
1024 
1025 static void
tls_tcp_send_cb(void * arg)1026 tls_tcp_send_cb(void *arg)
1027 {
1028 	tls_conn *conn = arg;
1029 	nng_aio * aio  = &conn->tcp_send;
1030 	int       rv;
1031 	size_t    count;
1032 
1033 	nni_mtx_lock(&conn->lock);
1034 	conn->tcp_send_active = false;
1035 
1036 	if ((rv = nni_aio_result(aio)) != 0) {
1037 		tls_tcp_error(conn, rv);
1038 		nni_mtx_unlock(&conn->lock);
1039 		return;
1040 	}
1041 
1042 	count = nni_aio_count(aio);
1043 	NNI_ASSERT(count <= conn->tcp_send_len);
1044 	conn->tcp_send_len -= count;
1045 	conn->tcp_send_tail += count;
1046 	conn->tcp_send_tail %= NNG_TLS_MAX_SEND_SIZE;
1047 	tls_tcp_send_start(conn);
1048 
1049 	if (tls_do_handshake(conn)) {
1050 		tls_do_send(conn);
1051 		tls_do_recv(conn);
1052 	}
1053 
1054 	nni_mtx_unlock(&conn->lock);
1055 }
1056 
1057 static void
tls_tcp_recv_cb(void * arg)1058 tls_tcp_recv_cb(void *arg)
1059 {
1060 	tls_conn *conn = arg;
1061 	nni_aio * aio  = &conn->tcp_recv;
1062 	int       rv;
1063 
1064 	nni_mtx_lock(&conn->lock);
1065 
1066 	conn->tcp_recv_pend = false;
1067 	if ((rv = nni_aio_result(aio)) != 0) {
1068 		tls_tcp_error(conn, rv);
1069 		nni_mtx_unlock(&conn->lock);
1070 		return;
1071 	}
1072 
1073 	NNI_ASSERT(conn->tcp_recv_len == 0);
1074 	NNI_ASSERT(conn->tcp_recv_off == 0);
1075 	conn->tcp_recv_len = nni_aio_count(aio);
1076 
1077 	if (tls_do_handshake(conn)) {
1078 		tls_do_recv(conn);
1079 		tls_do_send(conn);
1080 	}
1081 
1082 	nni_mtx_unlock(&conn->lock);
1083 }
1084 
1085 static void
tls_tcp_recv_start(tls_conn * conn)1086 tls_tcp_recv_start(tls_conn *conn)
1087 {
1088 	nng_iov iov;
1089 
1090 	if (conn->tcp_recv_len != 0) {
1091 		// We already have data in the buffer.
1092 		return;
1093 	}
1094 	if (conn->tcp_recv_pend) {
1095 		// Already have a receive in flight.
1096 		return;
1097 	}
1098 	conn->tcp_recv_off = 0;
1099 	iov.iov_len        = NNG_TLS_MAX_RECV_SIZE;
1100 	iov.iov_buf        = conn->tcp_recv_buf;
1101 
1102 	conn->tcp_recv_pend = true;
1103 	nng_aio_set_iov(&conn->tcp_recv, 1, &iov);
1104 
1105 	nng_stream_recv(conn->tcp, &conn->tcp_recv);
1106 }
1107 
1108 static void
tls_tcp_send_start(tls_conn * conn)1109 tls_tcp_send_start(tls_conn *conn)
1110 {
1111 	nni_iov  iov[2];
1112 	unsigned nio = 0;
1113 	size_t   len;
1114 	size_t   tail;
1115 	size_t   head;
1116 
1117 	if (conn->tcp_send_active) {
1118 		return;
1119 	}
1120 	if (conn->tcp_send_len == 0) {
1121 		return;
1122 	}
1123 	len  = conn->tcp_send_len;
1124 	head = conn->tcp_send_head;
1125 	tail = conn->tcp_send_tail;
1126 
1127 	while (len > 0) {
1128 		size_t cnt;
1129 		NNI_ASSERT(nio < 2);
1130 		if (tail < head) {
1131 			cnt = head - tail;
1132 		} else {
1133 			cnt = NNG_TLS_MAX_SEND_SIZE - tail;
1134 		}
1135 		if (cnt > len) {
1136 			cnt = len;
1137 		}
1138 		iov[nio].iov_buf = conn->tcp_send_buf + tail;
1139 		iov[nio].iov_len = cnt;
1140 		len -= cnt;
1141 		tail += cnt;
1142 		tail %= NNG_TLS_MAX_SEND_SIZE;
1143 		nio++;
1144 	}
1145 	conn->tcp_send_active = true;
1146 	nni_aio_set_iov(&conn->tcp_send, nio, iov);
1147 	nng_stream_send(conn->tcp, &conn->tcp_send);
1148 }
1149 
1150 int
nng_tls_engine_send(void * arg,const uint8_t * buf,size_t * szp)1151 nng_tls_engine_send(void *arg, const uint8_t *buf, size_t *szp)
1152 {
1153 	tls_conn *conn = arg;
1154 	size_t    len  = *szp;
1155 	size_t    head = conn->tcp_send_head;
1156 	size_t    tail = conn->tcp_send_tail;
1157 	size_t    space;
1158 	size_t    cnt;
1159 
1160 	space = NNG_TLS_MAX_SEND_SIZE - conn->tcp_send_len;
1161 
1162 	if (space == 0) {
1163 		return (NNG_EAGAIN);
1164 	}
1165 
1166 	if (conn->closed) {
1167 		return (NNG_ECLOSED);
1168 	}
1169 
1170 	if (len > space) {
1171 		len = space;
1172 	}
1173 
1174 	// We are committed at this point to sending out len bytes.
1175 	// Update this now, so that we can use len to update.
1176 	*szp = len;
1177 	conn->tcp_send_len += len;
1178 	NNI_ASSERT(conn->tcp_send_len <= NNG_TLS_MAX_SEND_SIZE);
1179 
1180 	while (len > 0) {
1181 		if (head >= tail) {
1182 			cnt = NNG_TLS_MAX_SEND_SIZE - head;
1183 		} else {
1184 			cnt = tail - head;
1185 		}
1186 		if (cnt > len) {
1187 			cnt = len;
1188 		}
1189 
1190 		memcpy(conn->tcp_send_buf + head, buf, cnt);
1191 		buf += cnt;
1192 		head += cnt;
1193 		head %= NNG_TLS_MAX_SEND_SIZE;
1194 		len -= cnt;
1195 	}
1196 
1197 	conn->tcp_send_head = head;
1198 
1199 	tls_tcp_send_start(conn);
1200 	return (0);
1201 }
1202 
1203 int
nng_tls_engine_recv(void * arg,uint8_t * buf,size_t * szp)1204 nng_tls_engine_recv(void *arg, uint8_t *buf, size_t *szp)
1205 {
1206 	tls_conn *conn = arg;
1207 	size_t    len  = *szp;
1208 
1209 	if (conn->closed) {
1210 		return (NNG_ECLOSED);
1211 	}
1212 	if (conn->tcp_recv_len == 0) {
1213 		tls_tcp_recv_start(conn);
1214 		return (NNG_EAGAIN);
1215 	}
1216 	if (len > conn->tcp_recv_len) {
1217 		len = conn->tcp_recv_len;
1218 	}
1219 	memcpy(buf, conn->tcp_recv_buf + conn->tcp_recv_off, len);
1220 	conn->tcp_recv_off += len;
1221 	conn->tcp_recv_len -= len;
1222 
1223 	// If we still have data left in the buffer, then the following
1224 	// call is a no-op.
1225 	tls_tcp_recv_start(conn);
1226 
1227 	*szp = len;
1228 	return (0);
1229 }
1230 
1231 int
nng_tls_config_cert_key_file(nng_tls_config * cfg,const char * path,const char * pass)1232 nng_tls_config_cert_key_file(
1233     nng_tls_config *cfg, const char *path, const char *pass)
1234 {
1235 	int    rv;
1236 	void * data;
1237 	size_t size;
1238 	char * pem;
1239 
1240 	if ((rv = nni_file_get(path, &data, &size)) != 0) {
1241 		return (rv);
1242 	}
1243 	if ((pem = nni_zalloc(size + 1)) == NULL) {
1244 		nni_free(data, size);
1245 		return (NNG_ENOMEM);
1246 	}
1247 	memcpy(pem, data, size);
1248 	nni_free(data, size);
1249 	rv = nng_tls_config_own_cert(cfg, pem, pem, pass);
1250 	nni_free(pem, size + 1);
1251 	return (rv);
1252 }
1253 
1254 int
nng_tls_config_ca_file(nng_tls_config * cfg,const char * path)1255 nng_tls_config_ca_file(nng_tls_config *cfg, const char *path)
1256 {
1257 	int    rv;
1258 	void * data;
1259 	size_t size;
1260 	char * pem;
1261 
1262 	if ((rv = nni_file_get(path, &data, &size)) != 0) {
1263 		return (rv);
1264 	}
1265 	if ((pem = nni_zalloc(size + 1)) == NULL) {
1266 		nni_free(data, size);
1267 		return (NNG_ENOMEM);
1268 	}
1269 	memcpy(pem, data, size);
1270 	nni_free(data, size);
1271 	if (strstr(pem, "-----BEGIN X509 CRL-----") != NULL) {
1272 		rv = nng_tls_config_ca_chain(cfg, pem, pem);
1273 	} else {
1274 		rv = nng_tls_config_ca_chain(cfg, pem, NULL);
1275 	}
1276 	nni_free(pem, size + 1);
1277 	return (rv);
1278 }
1279 
1280 int
nng_tls_config_version(nng_tls_config * cfg,nng_tls_version min_ver,nng_tls_version max_ver)1281 nng_tls_config_version(
1282     nng_tls_config *cfg, nng_tls_version min_ver, nng_tls_version max_ver)
1283 {
1284 	int rv;
1285 
1286 	nni_mtx_lock(&cfg->lock);
1287 	if (cfg->busy != 0) {
1288 		rv = NNG_EBUSY;
1289 	} else {
1290 		rv = cfg->ops.version((void *) (cfg + 1), min_ver, max_ver);
1291 	}
1292 	nni_mtx_unlock(&cfg->lock);
1293 	return (rv);
1294 }
1295 
1296 int
nng_tls_config_server_name(nng_tls_config * cfg,const char * name)1297 nng_tls_config_server_name(nng_tls_config *cfg, const char *name)
1298 {
1299 	int rv;
1300 
1301 	nni_mtx_lock(&cfg->lock);
1302 	if (cfg->busy != 0) {
1303 		rv = NNG_EBUSY;
1304 	} else {
1305 		rv = cfg->ops.server((void *) (cfg + 1), name);
1306 	}
1307 	nni_mtx_unlock(&cfg->lock);
1308 	return (rv);
1309 }
1310 
1311 int
nng_tls_config_ca_chain(nng_tls_config * cfg,const char * certs,const char * crl)1312 nng_tls_config_ca_chain(
1313     nng_tls_config *cfg, const char *certs, const char *crl)
1314 {
1315 	int rv;
1316 
1317 	nni_mtx_lock(&cfg->lock);
1318 	if (cfg->busy != 0) {
1319 		rv = NNG_EBUSY;
1320 	} else {
1321 		rv = cfg->ops.ca_chain((void *) (cfg + 1), certs, crl);
1322 	}
1323 	nni_mtx_unlock(&cfg->lock);
1324 	return (rv);
1325 }
1326 
1327 int
nng_tls_config_own_cert(nng_tls_config * cfg,const char * cert,const char * key,const char * pass)1328 nng_tls_config_own_cert(
1329     nng_tls_config *cfg, const char *cert, const char *key, const char *pass)
1330 {
1331 	int rv;
1332 	nni_mtx_lock(&cfg->lock);
1333 	if (cfg->busy != 0) {
1334 		rv = NNG_EBUSY;
1335 	} else {
1336 		rv = cfg->ops.own_cert((void *) (cfg + 1), cert, key, pass);
1337 	}
1338 	nni_mtx_unlock(&cfg->lock);
1339 	return (rv);
1340 }
1341 
1342 int
nng_tls_config_auth_mode(nng_tls_config * cfg,nng_tls_auth_mode mode)1343 nng_tls_config_auth_mode(nng_tls_config *cfg, nng_tls_auth_mode mode)
1344 {
1345 	int rv;
1346 
1347 	nni_mtx_lock(&cfg->lock);
1348 	if (cfg->busy != 0) {
1349 		rv = NNG_EBUSY;
1350 	} else {
1351 		rv = cfg->ops.auth((void *) (cfg + 1), mode);
1352 	}
1353 	nni_mtx_unlock(&cfg->lock);
1354 	return (rv);
1355 }
1356 
1357 int
nng_tls_config_alloc(nng_tls_config ** cfg_p,nng_tls_mode mode)1358 nng_tls_config_alloc(nng_tls_config **cfg_p, nng_tls_mode mode)
1359 {
1360 	nng_tls_config *      cfg;
1361 	const nng_tls_engine *eng;
1362 	size_t                size;
1363 	int                   rv;
1364 
1365 	if ((rv = nni_init()) != 0) {
1366 		return (rv);
1367 	}
1368 
1369 	nni_mtx_lock(&tls_engine_lock);
1370 	eng = tls_engine;
1371 	nni_mtx_unlock(&tls_engine_lock);
1372 
1373 	if (eng == NULL) {
1374 		return (NNG_ENOTSUP);
1375 	}
1376 
1377 	size = NNI_ALIGN_UP(sizeof(*cfg)) + eng->config_ops->size;
1378 
1379 	if ((cfg = nni_zalloc(size)) == NULL) {
1380 		return (NNG_ENOMEM);
1381 	}
1382 
1383 	cfg->ops    = *eng->config_ops;
1384 	cfg->size   = size;
1385 	cfg->engine = eng;
1386 	cfg->ref    = 1;
1387 	cfg->busy   = 0;
1388 	nni_mtx_init(&cfg->lock);
1389 
1390 	if ((rv = cfg->ops.init((void *) (cfg + 1), mode)) != 0) {
1391 		nni_free(cfg, cfg->size);
1392 		return (rv);
1393 	}
1394 	*cfg_p = cfg;
1395 	return (0);
1396 }
1397 
1398 void
nng_tls_config_free(nng_tls_config * cfg)1399 nng_tls_config_free(nng_tls_config *cfg)
1400 {
1401 	nni_mtx_lock(&cfg->lock);
1402 	cfg->ref--;
1403 	if (cfg->ref != 0) {
1404 		nni_mtx_unlock(&cfg->lock);
1405 		return;
1406 	}
1407 	nni_mtx_unlock(&cfg->lock);
1408 	nni_mtx_fini(&cfg->lock);
1409 	cfg->ops.fini((void *) (cfg + 1));
1410 	nni_free(cfg, cfg->size);
1411 }
1412 
1413 void
nng_tls_config_hold(nng_tls_config * cfg)1414 nng_tls_config_hold(nng_tls_config *cfg)
1415 {
1416 	nni_mtx_lock(&cfg->lock);
1417 	cfg->ref++;
1418 	nni_mtx_unlock(&cfg->lock);
1419 }
1420 
1421 const char *
nng_tls_engine_name(void)1422 nng_tls_engine_name(void)
1423 {
1424 	const nng_tls_engine *eng;
1425 
1426 	nni_init();
1427 	nni_mtx_lock(&tls_engine_lock);
1428 	eng = tls_engine;
1429 	nni_mtx_unlock(&tls_engine_lock);
1430 
1431 	return (eng == NULL ? "none" : eng->name);
1432 }
1433 
1434 const char *
nng_tls_engine_description(void)1435 nng_tls_engine_description(void)
1436 {
1437 	const nng_tls_engine *eng;
1438 
1439 	nni_init();
1440 	nni_mtx_lock(&tls_engine_lock);
1441 	eng = tls_engine;
1442 	nni_mtx_unlock(&tls_engine_lock);
1443 
1444 	return (eng == NULL ? "" : eng->description);
1445 }
1446 
1447 bool
nng_tls_engine_fips_mode(void)1448 nng_tls_engine_fips_mode(void)
1449 {
1450 	const nng_tls_engine *eng;
1451 
1452 	nni_init();
1453 	nni_mtx_lock(&tls_engine_lock);
1454 	eng = tls_engine;
1455 	nni_mtx_unlock(&tls_engine_lock);
1456 
1457 	return (eng == NULL ? false : eng->fips_mode);
1458 }
1459 
1460 int
nng_tls_engine_register(const nng_tls_engine * engine)1461 nng_tls_engine_register(const nng_tls_engine *engine)
1462 {
1463 	if (engine->version != NNG_TLS_ENGINE_VERSION) {
1464 		return (NNG_ENOTSUP);
1465 	}
1466 	nni_mtx_lock(&tls_engine_lock);
1467 	tls_engine = engine;
1468 	nni_mtx_unlock(&tls_engine_lock);
1469 	return (0);
1470 }
1471 
1472 #ifdef NNG_TLS_ENGINE_INIT
1473 extern int NNG_TLS_ENGINE_INIT(void);
1474 #else
1475 static int
NNG_TLS_ENGINE_INIT(void)1476 NNG_TLS_ENGINE_INIT(void)
1477 {
1478 	return (0);
1479 }
1480 #endif
1481 
1482 #ifdef NNG_TLS_ENGINE_FINI
1483 extern void NNG_TLS_ENGINE_FINI(void);
1484 #else
1485 static void
NNG_TLS_ENGINE_FINI(void)1486 NNG_TLS_ENGINE_FINI(void)
1487 {
1488 }
1489 #endif
1490 
1491 int
nni_tls_sys_init(void)1492 nni_tls_sys_init(void)
1493 {
1494 	int rv;
1495 	nni_mtx_init(&tls_engine_lock);
1496 	tls_engine = NULL;
1497 
1498 	rv = NNG_TLS_ENGINE_INIT();
1499 	if (rv != 0) {
1500 		nni_mtx_fini(&tls_engine_lock);
1501 		return (rv);
1502 	}
1503 	return (0);
1504 }
1505 
1506 void
nni_tls_sys_fini(void)1507 nni_tls_sys_fini(void)
1508 {
1509 	nni_reap_drain();
1510 	NNG_TLS_ENGINE_FINI();
1511 }
1512 
1513 #else // NNG_SUPP_TLS
1514 
1515 // Provide stubs for the case where TLS is not enabled.
1516 void
nni_tls_config_fini(nng_tls_config * cfg)1517 nni_tls_config_fini(nng_tls_config *cfg)
1518 {
1519 	NNI_ARG_UNUSED(cfg);
1520 }
1521 
1522 int
nni_tls_config_init(nng_tls_config ** cpp,enum nng_tls_mode mode)1523 nni_tls_config_init(nng_tls_config **cpp, enum nng_tls_mode mode)
1524 {
1525 	NNI_ARG_UNUSED(cpp);
1526 	NNI_ARG_UNUSED(mode);
1527 	return (NNG_ENOTSUP);
1528 }
1529 
1530 void
nni_tls_config_hold(nng_tls_config * cfg)1531 nni_tls_config_hold(nng_tls_config *cfg)
1532 {
1533 	NNI_ARG_UNUSED(cfg);
1534 }
1535 
1536 int
nng_tls_config_server_name(nng_tls_config * cfg,const char * name)1537 nng_tls_config_server_name(nng_tls_config *cfg, const char *name)
1538 {
1539 	NNI_ARG_UNUSED(cfg);
1540 	NNI_ARG_UNUSED(name);
1541 	return (NNG_ENOTSUP);
1542 }
1543 
1544 int
nng_tls_config_auth_mode(nng_tls_config * cfg,nng_tls_auth_mode mode)1545 nng_tls_config_auth_mode(nng_tls_config *cfg, nng_tls_auth_mode mode)
1546 {
1547 	NNI_ARG_UNUSED(cfg);
1548 	NNI_ARG_UNUSED(mode);
1549 	return (NNG_ENOTSUP);
1550 }
1551 
1552 int
nng_tls_config_ca_chain(nng_tls_config * cfg,const char * certs,const char * crl)1553 nng_tls_config_ca_chain(
1554     nng_tls_config *cfg, const char *certs, const char *crl)
1555 {
1556 	NNI_ARG_UNUSED(cfg);
1557 	NNI_ARG_UNUSED(certs);
1558 	NNI_ARG_UNUSED(crl);
1559 	return (NNG_ENOTSUP);
1560 }
1561 
1562 int
nng_tls_config_own_cert(nng_tls_config * cfg,const char * cert,const char * key,const char * pass)1563 nng_tls_config_own_cert(
1564     nng_tls_config *cfg, const char *cert, const char *key, const char *pass)
1565 {
1566 	NNI_ARG_UNUSED(cfg);
1567 	NNI_ARG_UNUSED(cert);
1568 	NNI_ARG_UNUSED(key);
1569 	NNI_ARG_UNUSED(pass);
1570 	return (NNG_ENOTSUP);
1571 }
1572 
1573 int
nng_tls_config_ca_file(nng_tls_config * cfg,const char * path)1574 nng_tls_config_ca_file(nng_tls_config *cfg, const char *path)
1575 {
1576 	NNI_ARG_UNUSED(cfg);
1577 	NNI_ARG_UNUSED(path);
1578 	return (NNG_ENOTSUP);
1579 }
1580 
1581 int
nng_tls_config_cert_key_file(nng_tls_config * cfg,const char * path,const char * pass)1582 nng_tls_config_cert_key_file(
1583     nng_tls_config *cfg, const char *path, const char *pass)
1584 {
1585 	NNI_ARG_UNUSED(cfg);
1586 	NNI_ARG_UNUSED(path);
1587 	NNI_ARG_UNUSED(pass);
1588 	return (NNG_ENOTSUP);
1589 }
1590 
1591 int
nng_tls_config_key(nng_tls_config * cfg,const uint8_t * key,size_t size)1592 nng_tls_config_key(nng_tls_config *cfg, const uint8_t *key, size_t size)
1593 {
1594 	NNI_ARG_UNUSED(cfg);
1595 	NNI_ARG_UNUSED(key);
1596 	NNI_ARG_UNUSED(size);
1597 	return (NNG_ENOTSUP);
1598 }
1599 
1600 int
nng_tls_config_pass(nng_tls_config * cfg,const char * pass)1601 nng_tls_config_pass(nng_tls_config *cfg, const char *pass)
1602 {
1603 	NNI_ARG_UNUSED(cfg);
1604 	NNI_ARG_UNUSED(pass);
1605 	return (NNG_ENOTSUP);
1606 }
1607 
1608 int
nng_tls_config_alloc(nng_tls_config ** cfgp,nng_tls_mode mode)1609 nng_tls_config_alloc(nng_tls_config **cfgp, nng_tls_mode mode)
1610 {
1611 
1612 	NNI_ARG_UNUSED(cfgp);
1613 	NNI_ARG_UNUSED(mode);
1614 	return (NNG_ENOTSUP);
1615 }
1616 
1617 void
nng_tls_config_free(nng_tls_config * cfg)1618 nng_tls_config_free(nng_tls_config *cfg)
1619 {
1620 	NNI_ARG_UNUSED(cfg);
1621 }
1622 
1623 int
nng_tls_config_version(nng_tls_config * cfg,nng_tls_version min_ver,nng_tls_version max_ver)1624 nng_tls_config_version(
1625     nng_tls_config *cfg, nng_tls_version min_ver, nng_tls_version max_ver)
1626 {
1627 	NNI_ARG_UNUSED(cfg);
1628 	NNI_ARG_UNUSED(min_ver);
1629 	NNI_ARG_UNUSED(max_ver);
1630 	return (NNG_ENOTSUP);
1631 }
1632 
1633 int
nni_tls_dialer_alloc(nng_stream_dialer ** dp,const nng_url * url)1634 nni_tls_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)
1635 {
1636 	NNI_ARG_UNUSED(dp);
1637 	NNI_ARG_UNUSED(url);
1638 	return (NNG_ENOTSUP);
1639 }
1640 
1641 int
nni_tls_listener_alloc(nng_stream_listener ** lp,const nng_url * url)1642 nni_tls_listener_alloc(nng_stream_listener **lp, const nng_url *url)
1643 {
1644 	NNI_ARG_UNUSED(lp);
1645 	NNI_ARG_UNUSED(url);
1646 	return (NNG_ENOTSUP);
1647 }
1648 
1649 int
nni_tls_checkopt(const char * nm,const void * buf,size_t sz,nni_type t)1650 nni_tls_checkopt(const char *nm, const void *buf, size_t sz, nni_type t)
1651 {
1652 	NNI_ARG_UNUSED(nm);
1653 	NNI_ARG_UNUSED(buf);
1654 	NNI_ARG_UNUSED(sz);
1655 	NNI_ARG_UNUSED(t);
1656 	return (NNG_ENOTSUP);
1657 }
1658 
1659 const char *
nng_tls_engine_name(void)1660 nng_tls_engine_name(void)
1661 {
1662 	return ("none");
1663 }
1664 
1665 const char *
nng_tls_engine_description(void)1666 nng_tls_engine_description(void)
1667 {
1668 	return ("");
1669 }
1670 
1671 bool
nng_tls_engine_fips_mode(void)1672 nng_tls_engine_fips_mode(void)
1673 {
1674 	return (false);
1675 }
1676 
1677 int
nng_tls_engine_register(const nng_tls_engine * engine)1678 nng_tls_engine_register(const nng_tls_engine *engine)
1679 {
1680 	NNI_ARG_UNUSED(engine);
1681 	return (NNG_ENOTSUP);
1682 }
1683 
1684 int
nni_tls_sys_init(void)1685 nni_tls_sys_init(void)
1686 {
1687 	return (0);
1688 }
1689 
1690 void
nni_tls_sys_fini(void)1691 nni_tls_sys_fini(void)
1692 {
1693 }
1694 
1695 #endif // !NNG_SUPP_TLS