ReactOS 0.4.16-dev-1741-g9ab8761
altcp_tls_mbedtls.c
Go to the documentation of this file.
1
10/*
11 * Copyright (c) 2017 Simon Goldschmidt
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright notice,
18 * this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
20 * this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22 * 3. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 * OF SUCH DAMAGE.
35 *
36 * This file is part of the lwIP TCP/IP stack.
37 *
38 * Author: Simon Goldschmidt <goldsimon@gmx.de>
39 *
40 * Watch out:
41 * - 'sent' is always called with len==0 to the upper layer. This is because keeping
42 * track of the ratio of application data and TLS overhead would be too much.
43 *
44 * Mandatory security-related configuration:
45 * - ensure to add at least one strong entropy source to your mbedtls port (implement
46 * mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong entropy)
47 * - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing
48 * GOOD custom entropy
49 *
50 * Missing things / @todo:
51 * - some unhandled/untested things migh be caught by LWIP_ASSERTs...
52 */
53
54#include "lwip/opt.h"
55#include "lwip/sys.h"
56
57#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
58
60
61#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS
62
63#include "lwip/altcp.h"
64#include "lwip/altcp_tls.h"
66
69
70/* @todo: which includes are really needed? */
71#include "mbedtls/entropy.h"
72#include "mbedtls/ctr_drbg.h"
73#include "mbedtls/certs.h"
74#include "mbedtls/x509.h"
75#include "mbedtls/ssl.h"
76#include "mbedtls/net_sockets.h"
77#include "mbedtls/error.h"
78#include "mbedtls/debug.h"
79#include "mbedtls/platform.h"
81#include "mbedtls/ssl_cache.h"
82#include "mbedtls/ssl_ticket.h"
83
84#include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */
85
86#include <string.h>
87
88#ifndef ALTCP_MBEDTLS_ENTROPY_PTR
89#define ALTCP_MBEDTLS_ENTROPY_PTR NULL
90#endif
91#ifndef ALTCP_MBEDTLS_ENTROPY_LEN
92#define ALTCP_MBEDTLS_ENTROPY_LEN 0
93#endif
94#ifndef ALTCP_MBEDTLS_RNG_FN
95#define ALTCP_MBEDTLS_RNG_FN mbedtls_entropy_func
96#endif
97
98/* Variable prototype, the actual declaration is at the end of this file
99 since it contains pointers to static functions declared here */
100extern const struct altcp_functions altcp_mbedtls_functions;
101
103struct altcp_tls_config {
106 mbedtls_pk_context *pkey;
107 u8_t cert_count;
108 u8_t cert_max;
109 u8_t pkey_count;
110 u8_t pkey_max;
112#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE
115#endif
116#if defined(MBEDTLS_SSL_SESSION_TICKETS) && ALTCP_MBEDTLS_USE_SESSION_TICKETS
118#endif
119};
120
122struct altcp_tls_entropy_rng {
125 int ref;
126};
127static struct altcp_tls_entropy_rng *altcp_tls_entropy_rng;
128
129static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err);
130static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn);
131static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
132static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
133static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size);
134
135
136/* callback functions from inner/lower connection: */
137
143static err_t
144altcp_mbedtls_lower_accept(void *arg, struct altcp_pcb *accepted_conn, err_t err)
145{
146 struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg;
147 if (listen_conn && listen_conn->state && listen_conn->accept) {
148 err_t setup_err;
149 altcp_mbedtls_state_t *listen_state = (altcp_mbedtls_state_t *)listen_conn->state;
150 /* create a new altcp_conn to pass to the next 'accept' callback */
151 struct altcp_pcb *new_conn = altcp_alloc();
152 if (new_conn == NULL) {
153 return ERR_MEM;
154 }
155 setup_err = altcp_mbedtls_setup(listen_state->conf, new_conn, accepted_conn);
156 if (setup_err != ERR_OK) {
157 altcp_free(new_conn);
158 return setup_err;
159 }
160 return listen_conn->accept(listen_conn->arg, new_conn, err);
161 }
162 return ERR_ARG;
163}
164
168static err_t
169altcp_mbedtls_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err)
170{
171 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
172 LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
173 if (conn && conn->state) {
174 altcp_mbedtls_state_t *state;
175 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
176 /* upper connected is called when handshake is done */
177 if (err != ERR_OK) {
178 if (conn->connected) {
179 return conn->connected(conn->arg, conn, err);
180 }
181 }
182 state = (altcp_mbedtls_state_t *)conn->state;
183 /* ensure overhead value is valid before first write */
184 state->overhead_bytes_adjust = 0;
185 return altcp_mbedtls_lower_recv_process(conn, state);
186 }
187 return ERR_VAL;
188}
189
190/* Call recved for possibly more than an u16_t */
191static void
192altcp_mbedtls_lower_recved(struct altcp_pcb *inner_conn, int recvd_cnt)
193{
194 while (recvd_cnt > 0) {
195 u16_t recvd_part = (u16_t)LWIP_MIN(recvd_cnt, 0xFFFF);
196 altcp_recved(inner_conn, recvd_part);
197 recvd_cnt -= recvd_part;
198 }
199}
200
205static err_t
206altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err)
207{
208 altcp_mbedtls_state_t *state;
209 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
210
211 LWIP_ASSERT("no err expected", err == ERR_OK);
213
214 if (!conn) {
215 /* no connection given as arg? should not happen, but prevent pbuf/conn leaks */
216 if (p != NULL) {
217 pbuf_free(p);
218 }
219 altcp_close(inner_conn);
220 return ERR_CLSD;
221 }
222 state = (altcp_mbedtls_state_t *)conn->state;
223 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
224 if (!state) {
225 /* already closed */
226 if (p != NULL) {
227 pbuf_free(p);
228 }
229 altcp_close(inner_conn);
230 return ERR_CLSD;
231 }
232
233 /* handle NULL pbuf (inner connection closed) */
234 if (p == NULL) {
235 /* remote host sent FIN, remember this (SSL state is destroyed
236 when both sides are closed only!) */
237 if ((state->flags & (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) ==
238 (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) {
239 /* need to notify upper layer (e.g. 'accept' called or 'connect' succeeded) */
240 if ((state->rx != NULL) || (state->rx_app != NULL)) {
241 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED;
242 /* this is a normal close (FIN) but we have unprocessed data, so delay the FIN */
243 altcp_mbedtls_handle_rx_appldata(conn, state);
244 return ERR_OK;
245 }
246 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
247 if (conn->recv) {
248 return conn->recv(conn->arg, conn, NULL, ERR_OK);
249 }
250 } else {
251 /* before connection setup is done: call 'err' */
252 if (conn->err) {
253 conn->err(conn->arg, ERR_ABRT);
254 }
255 altcp_close(conn);
256 }
257 return ERR_OK;
258 }
259
260 /* If we come here, the connection is in good state (handshake phase or application data phase).
261 Queue up the pbuf for processing as handshake data or application data. */
262 if (state->rx == NULL) {
263 state->rx = p;
264 } else {
265 LWIP_ASSERT("rx pbuf overflow", (int)p->tot_len + (int)p->len <= 0xFFFF);
266 pbuf_cat(state->rx, p);
267 }
268 return altcp_mbedtls_lower_recv_process(conn, state);
269}
270
271static err_t
272altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
273{
274 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
275 /* handle connection setup (handshake not done) */
276 int ret = mbedtls_ssl_handshake(&state->ssl_context);
277 /* try to send data... */
278 altcp_output(conn->inner_conn);
279 if (state->bio_bytes_read) {
280 /* acknowledge all bytes read */
281 altcp_mbedtls_lower_recved(conn->inner_conn, state->bio_bytes_read);
282 state->bio_bytes_read = 0;
283 }
284
286 /* handshake not done, wait for more recv calls */
287 LWIP_ASSERT("in this state, the rx chain should be empty", state->rx == NULL);
288 return ERR_OK;
289 }
290 if (ret != 0) {
291 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret));
292 /* handshake failed, connection has to be closed */
293 if (conn->err) {
294 conn->err(conn->arg, ERR_CLSD);
295 }
296
297 if (altcp_close(conn) != ERR_OK) {
298 altcp_abort(conn);
299 }
300 return ERR_OK;
301 }
302 /* If we come here, handshake succeeded. */
303 LWIP_ASSERT("state", state->bio_bytes_read == 0);
304 LWIP_ASSERT("state", state->bio_bytes_appl == 0);
305 state->flags |= ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE;
306 /* issue "connect" callback" to upper connection (this can only happen for active open) */
307 if (conn->connected) {
308 err_t err;
309 err = conn->connected(conn->arg, conn, ERR_OK);
310 if (err != ERR_OK) {
311 return err;
312 }
313 }
314 if (state->rx == NULL) {
315 return ERR_OK;
316 }
317 }
318 /* handle application data */
319 return altcp_mbedtls_handle_rx_appldata(conn, state);
320}
321
322/* Pass queued decoded rx data to application */
323static err_t
324altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
325{
326 err_t err;
327 struct pbuf *buf;
328 LWIP_ASSERT("conn != NULL", conn != NULL);
329 LWIP_ASSERT("state != NULL", state != NULL);
330 buf = state->rx_app;
331 if (buf) {
332 state->rx_app = NULL;
333 if (conn->recv) {
334 u16_t tot_len = buf->tot_len;
335 /* this needs to be increased first because the 'recved' call may come nested */
336 state->rx_passed_unrecved += tot_len;
337 state->flags |= ALTCP_MBEDTLS_FLAGS_UPPER_CALLED;
338 err = conn->recv(conn->arg, conn, buf, ERR_OK);
339 if (err != ERR_OK) {
340 if (err == ERR_ABRT) {
341 return ERR_ABRT;
342 }
343 /* not received, leave the pbuf(s) queued (and decrease 'unrecved' again) */
344 LWIP_ASSERT("state == conn->state", state == conn->state);
345 state->rx_app = buf;
346 state->rx_passed_unrecved -= tot_len;
347 LWIP_ASSERT("state->rx_passed_unrecved >= 0", state->rx_passed_unrecved >= 0);
348 if (state->rx_passed_unrecved < 0) {
349 state->rx_passed_unrecved = 0;
350 }
351 return err;
352 }
353 } else {
354 pbuf_free(buf);
355 }
356 } else if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
357 ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
358 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
359 if (conn->recv) {
360 return conn->recv(conn->arg, conn, NULL, ERR_OK);
361 }
362 }
363
364 /* application may have close the connection */
365 if (conn->state != state) {
366 /* return error code to ensure altcp_mbedtls_handle_rx_appldata() exits the loop */
367 return ERR_ARG;
368 }
369 return ERR_OK;
370}
371
372/* Helper function that processes rx application data stored in rx pbuf chain */
373static err_t
374altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
375{
376 int ret;
377 LWIP_ASSERT("state != NULL", state != NULL);
378 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
379 /* handshake not done yet */
380 return ERR_VAL;
381 }
382 do {
383 /* allocate a full-sized unchained PBUF_POOL: this is for RX! */
385 if (buf == NULL) {
386 /* We're short on pbufs, try again later from 'poll' or 'recv' callbacks.
387 @todo: close on excessive allocation failures or leave this up to upper conn? */
388 return ERR_OK;
389 }
390
391 /* decrypt application data, this pulls encrypted RX data off state->rx pbuf chain */
392 ret = mbedtls_ssl_read(&state->ssl_context, (unsigned char *)buf->payload, PBUF_POOL_BUFSIZE);
393 if (ret < 0) {
395 /* client is initiating a new connection using the same source port -> close connection or make handshake */
396 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("new connection on same source port\n"));
397 LWIP_ASSERT("TODO: new connection on same source port, close this connection", 0);
400 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was closed gracefully\n"));
401 } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
402 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was reset by peer\n"));
403 }
404 pbuf_free(buf);
405 return ERR_OK;
406 } else {
407 pbuf_free(buf);
408 return ERR_OK;
409 }
410 pbuf_free(buf);
411 altcp_abort(conn);
412 return ERR_ABRT;
413 } else {
414 err_t err;
415 if (ret) {
416 LWIP_ASSERT("bogus receive length", ret <= PBUF_POOL_BUFSIZE);
417 /* trim pool pbuf to actually decoded length */
419
420 state->bio_bytes_appl += ret;
421 if (mbedtls_ssl_get_bytes_avail(&state->ssl_context) == 0) {
422 /* Record is done, now we know the share between application and protocol bytes
423 and can adjust the RX window by the protocol bytes.
424 The rest is 'recved' by the application calling our 'recved' fn. */
425 int overhead_bytes;
426 LWIP_ASSERT("bogus byte counts", state->bio_bytes_read > state->bio_bytes_appl);
427 overhead_bytes = state->bio_bytes_read - state->bio_bytes_appl;
428 altcp_mbedtls_lower_recved(conn->inner_conn, overhead_bytes);
429 state->bio_bytes_read = 0;
430 state->bio_bytes_appl = 0;
431 }
432
433 if (state->rx_app == NULL) {
434 state->rx_app = buf;
435 } else {
436 pbuf_cat(state->rx_app, buf);
437 }
438 } else {
439 pbuf_free(buf);
440 buf = NULL;
441 }
442 err = altcp_mbedtls_pass_rx_data(conn, state);
443 if (err != ERR_OK) {
444 if (err == ERR_ABRT) {
445 /* recv callback needs to return this as the pcb is deallocated */
446 return ERR_ABRT;
447 }
448 /* we hide all other errors as we retry feeding the pbuf to the app later */
449 return ERR_OK;
450 }
451 }
452 } while (ret > 0);
453 return ERR_OK;
454}
455
459static int
460altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len)
461{
462 struct altcp_pcb *conn = (struct altcp_pcb *)ctx;
463 altcp_mbedtls_state_t *state;
464 struct pbuf *p;
465 u16_t ret;
466 u16_t copy_len;
467 err_t err;
468
469 LWIP_UNUSED_ARG(err); /* for LWIP_NOASSERT */
470 if ((conn == NULL) || (conn->state == NULL)) {
472 }
473 state = (altcp_mbedtls_state_t *)conn->state;
474 LWIP_ASSERT("state != NULL", state != NULL);
475 p = state->rx;
476
477 /* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */
478
479 if ((p == NULL) || ((p->len == 0) && (p->next == NULL))) {
480 if (p) {
481 pbuf_free(p);
482 }
483 state->rx = NULL;
484 if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
485 ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
486 /* close queued but not passed up yet */
487 return 0;
488 }
490 }
491 /* limit number of bytes again to copy from first pbuf in a chain only */
492 copy_len = (u16_t)LWIP_MIN(len, p->len);
493 /* copy the data */
494 ret = pbuf_copy_partial(p, buf, copy_len, 0);
495 LWIP_ASSERT("ret == copy_len", ret == copy_len);
496 /* hide the copied bytes from the pbuf */
498 LWIP_ASSERT("error", err == ERR_OK);
499 if (p->len == 0) {
500 /* the first pbuf has been fully read, free it */
501 state->rx = p->next;
502 p->next = NULL;
503 pbuf_free(p);
504 }
505
506 state->bio_bytes_read += (int)ret;
507 return ret;
508}
509
515static err_t
516altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len)
517{
518 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
519 LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
520 if (conn) {
521 int overhead;
522 u16_t app_len;
523 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
524 LWIP_ASSERT("state", state != NULL);
525 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
526 /* calculate TLS overhead part to not send it to application */
527 overhead = state->overhead_bytes_adjust + state->ssl_context.out_left;
528 if ((unsigned)overhead > len) {
529 overhead = len;
530 }
531 /* remove ACKed bytes from overhead adjust counter */
532 state->overhead_bytes_adjust -= len;
533 /* try to send more if we failed before (may increase overhead adjust counter) */
534 mbedtls_ssl_flush_output(&state->ssl_context);
535 /* remove calculated overhead from ACKed bytes len */
536 app_len = len - (u16_t)overhead;
537 /* update application write counter and inform application */
538 if (app_len) {
539 state->overhead_bytes_adjust += app_len;
540 if (conn->sent)
541 return conn->sent(conn->arg, conn, app_len);
542 }
543 }
544 return ERR_OK;
545}
546
551static err_t
552altcp_mbedtls_lower_poll(void *arg, struct altcp_pcb *inner_conn)
553{
554 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
555 LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */
556 if (conn) {
557 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
558 /* check if there's unreceived rx data */
559 if (conn->state) {
560 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
561 /* try to send more if we failed before */
562 mbedtls_ssl_flush_output(&state->ssl_context);
563 if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) {
564 return ERR_ABRT;
565 }
566 }
567 if (conn->poll) {
568 return conn->poll(conn->arg, conn);
569 }
570 }
571 return ERR_OK;
572}
573
574static void
575altcp_mbedtls_lower_err(void *arg, err_t err)
576{
577 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
578 if (conn) {
579 conn->inner_conn = NULL; /* already freed */
580 if (conn->err) {
581 conn->err(conn->arg, err);
582 }
583 altcp_free(conn);
584 }
585}
586
587/* setup functions */
588
589static void
590altcp_mbedtls_remove_callbacks(struct altcp_pcb *inner_conn)
591{
592 altcp_arg(inner_conn, NULL);
593 altcp_recv(inner_conn, NULL);
594 altcp_sent(inner_conn, NULL);
595 altcp_err(inner_conn, NULL);
596 altcp_poll(inner_conn, NULL, inner_conn->pollinterval);
597}
598
599static void
600altcp_mbedtls_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
601{
602 altcp_arg(inner_conn, conn);
603 altcp_recv(inner_conn, altcp_mbedtls_lower_recv);
604 altcp_sent(inner_conn, altcp_mbedtls_lower_sent);
605 altcp_err(inner_conn, altcp_mbedtls_lower_err);
606 /* tcp_poll is set when interval is set by application */
607 /* listen is set totally different :-) */
608}
609
610static err_t
611altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
612{
613 int ret;
614 struct altcp_tls_config *config = (struct altcp_tls_config *)conf;
615 altcp_mbedtls_state_t *state;
616 if (!conf) {
617 return ERR_ARG;
618 }
619 LWIP_ASSERT("invalid inner_conn", conn != inner_conn);
620
621 /* allocate mbedtls context */
622 state = altcp_mbedtls_alloc(conf);
623 if (state == NULL) {
624 return ERR_MEM;
625 }
626 /* initialize mbedtls context: */
627 mbedtls_ssl_init(&state->ssl_context);
628 ret = mbedtls_ssl_setup(&state->ssl_context, &config->conf);
629 if (ret != 0) {
630 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_setup failed\n"));
631 /* @todo: convert 'ret' to err_t */
632 altcp_mbedtls_free(conf, state);
633 return ERR_MEM;
634 }
635 /* tell mbedtls about our I/O functions */
636 mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL);
637
638 altcp_mbedtls_setup_callbacks(conn, inner_conn);
639 conn->inner_conn = inner_conn;
640 conn->fns = &altcp_mbedtls_functions;
641 conn->state = state;
642 return ERR_OK;
643}
644
645struct altcp_pcb *
646altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb)
647{
648 struct altcp_pcb *ret;
649 if (inner_pcb == NULL) {
650 return NULL;
651 }
652 ret = altcp_alloc();
653 if (ret != NULL) {
654 if (altcp_mbedtls_setup(config, ret, inner_pcb) != ERR_OK) {
655 altcp_free(ret);
656 return NULL;
657 }
658 }
659 return ret;
660}
661
662void
663altcp_tls_init_session(struct altcp_tls_session *session)
664{
665 if (session)
667}
668
669err_t
670altcp_tls_get_session(struct altcp_pcb *conn, struct altcp_tls_session *session)
671{
672 if (session && conn && conn->state) {
673 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
674 int ret = mbedtls_ssl_get_session(&state->ssl_context, &session->data);
675 return ret < 0 ? ERR_VAL : ERR_OK;
676 }
677 return ERR_ARG;
678}
679
680err_t
681altcp_tls_set_session(struct altcp_pcb *conn, struct altcp_tls_session *session)
682{
683 if (session && conn && conn->state) {
684 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
685 int ret = -1;
686 if (session->data.start)
687 ret = mbedtls_ssl_set_session(&state->ssl_context, &session->data);
688 return ret < 0 ? ERR_VAL : ERR_OK;
689 }
690 return ERR_ARG;
691}
692
693void
694altcp_tls_free_session(struct altcp_tls_session *session)
695{
696 if (session)
698}
699
700void *
701altcp_tls_context(struct altcp_pcb *conn)
702{
703 if (conn && conn->state) {
704 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
705 return &state->ssl_context;
706 }
707 return NULL;
708}
709
710#if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF
711static void
712altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
713{
718
719 if (level >= ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN) {
720 LWIP_DEBUGF(ALTCP_MBEDTLS_LIB_DEBUG, ("%s:%04d: %s\n", file, line, str));
721 }
722}
723#endif
724
725static err_t
726altcp_mbedtls_ref_entropy(void)
727{
729
730 if (!altcp_tls_entropy_rng) {
731 altcp_tls_entropy_rng = (struct altcp_tls_entropy_rng *)altcp_mbedtls_alloc_config(sizeof(struct altcp_tls_entropy_rng));
732 if (altcp_tls_entropy_rng) {
733 int ret;
734 altcp_tls_entropy_rng->ref = 1;
735 mbedtls_entropy_init(&altcp_tls_entropy_rng->entropy);
736 mbedtls_ctr_drbg_init(&altcp_tls_entropy_rng->ctr_drbg);
737 /* Seed the RNG, only once */
738 ret = mbedtls_ctr_drbg_seed(&altcp_tls_entropy_rng->ctr_drbg,
739 ALTCP_MBEDTLS_RNG_FN, &altcp_tls_entropy_rng->entropy,
740 ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN);
741 if (ret != 0) {
742 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret));
743 mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg);
744 mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy);
745 altcp_mbedtls_free_config(altcp_tls_entropy_rng);
746 altcp_tls_entropy_rng = NULL;
747 return ERR_ARG;
748 }
749 } else {
750 return ERR_MEM;
751 }
752 } else {
753 altcp_tls_entropy_rng->ref++;
754 }
755 return ERR_OK;
756}
757
758static void
759altcp_mbedtls_unref_entropy(void)
760{
762
763 if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref) {
764 altcp_tls_entropy_rng->ref--;
765 }
766}
767
771static struct altcp_tls_config *
772altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int have_ca)
773{
774 size_t sz;
775 int ret;
776 struct altcp_tls_config *conf;
778
780 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS,
781 ("altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!\n"));
782 }
783
784 altcp_mbedtls_mem_init();
785
786 sz = sizeof(struct altcp_tls_config);
787 if (cert_count > 0) {
788 sz += (cert_count * sizeof(mbedtls_x509_crt));
789 }
790 if (have_ca) {
791 sz += sizeof(mbedtls_x509_crt);
792 }
793 if (pkey_count > 0) {
794 sz += (pkey_count * sizeof(mbedtls_pk_context));
795 }
796
797 conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz);
798 if (conf == NULL) {
799 return NULL;
800 }
801 conf->cert_max = cert_count;
802 mem = (mbedtls_x509_crt *)(conf + 1);
803 if (cert_count > 0) {
804 conf->cert = mem;
805 mem += cert_count;
806 }
807 if (have_ca) {
808 conf->ca = mem;
809 mem++;
810 }
811 conf->pkey_max = pkey_count;
812 if (pkey_count > 0) {
813 conf->pkey = (mbedtls_pk_context *)mem;
814 }
815
816 mbedtls_ssl_config_init(&conf->conf);
817
818 if (altcp_mbedtls_ref_entropy() != ERR_OK) {
819 altcp_mbedtls_free_config(conf);
820 return NULL;
821 }
822
823 /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */
826 if (ret != 0) {
827 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret));
828 altcp_mbedtls_unref_entropy();
829 altcp_mbedtls_free_config(conf);
830 return NULL;
831 }
832 mbedtls_ssl_conf_authmode(&conf->conf, ALTCP_MBEDTLS_AUTHMODE);
833
834 mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg);
835#if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF
836 mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout);
837#endif
838#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE
839 mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
840 mbedtls_ssl_cache_set_timeout(&conf->cache, ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS);
841 mbedtls_ssl_cache_set_max_entries(&conf->cache, ALTCP_MBEDTLS_SESSION_CACHE_SIZE);
842#endif
843
844#if defined(MBEDTLS_SSL_SESSION_TICKETS) && ALTCP_MBEDTLS_USE_SESSION_TICKETS
845 mbedtls_ssl_ticket_init(&conf->ticket_ctx);
846
847 ret = mbedtls_ssl_ticket_setup(&conf->ticket_ctx, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg,
848 ALTCP_MBEDTLS_SESSION_TICKET_CIPHER, ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS);
849 if (ret) {
850 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_ticket_setup failed: %d\n", ret));
851 altcp_mbedtls_unref_entropy();
852 altcp_mbedtls_free_config(conf);
853 return NULL;
854 }
855
856 mbedtls_ssl_conf_session_tickets_cb(&conf->conf, mbedtls_ssl_ticket_write, mbedtls_ssl_ticket_parse,
857 &conf->ticket_ctx);
858#endif
859
860 return conf;
861}
862
863struct altcp_tls_config *altcp_tls_create_config_server(u8_t cert_count)
864{
865 struct altcp_tls_config *conf = altcp_tls_create_config(1, cert_count, cert_count, 0);
866 if (conf == NULL) {
867 return NULL;
868 }
869
870 mbedtls_ssl_conf_ca_chain(&conf->conf, NULL, NULL);
871 return conf;
872}
873
874err_t altcp_tls_config_server_add_privkey_cert(struct altcp_tls_config *config,
875 const u8_t *privkey, size_t privkey_len,
876 const u8_t *privkey_pass, size_t privkey_pass_len,
877 const u8_t *cert, size_t cert_len)
878{
879 int ret;
880 mbedtls_x509_crt *srvcert;
881 mbedtls_pk_context *pkey;
882
883 if (config->cert_count >= config->cert_max) {
884 return ERR_MEM;
885 }
886 if (config->pkey_count >= config->pkey_max) {
887 return ERR_MEM;
888 }
889
890 srvcert = config->cert + config->cert_count;
891 mbedtls_x509_crt_init(srvcert);
892
893 pkey = config->pkey + config->pkey_count;
894 mbedtls_pk_init(pkey);
895
896 /* Load the certificates and private key */
897 ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len);
898 if (ret != 0) {
899 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret));
900 return ERR_VAL;
901 }
902
903 ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len);
904 if (ret != 0) {
905 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret));
906 mbedtls_x509_crt_free(srvcert);
907 return ERR_VAL;
908 }
909
910 ret = mbedtls_ssl_conf_own_cert(&config->conf, srvcert, pkey);
911 if (ret != 0) {
912 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret));
913 mbedtls_x509_crt_free(srvcert);
914 mbedtls_pk_free(pkey);
915 return ERR_VAL;
916 }
917
918 config->cert_count++;
919 config->pkey_count++;
920 return ERR_OK;
921}
922
927struct altcp_tls_config *
928altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
929 const u8_t *privkey_pass, size_t privkey_pass_len,
930 const u8_t *cert, size_t cert_len)
931{
932 struct altcp_tls_config *conf = altcp_tls_create_config_server(1);
933 if (conf == NULL) {
934 return NULL;
935 }
936
937 if (altcp_tls_config_server_add_privkey_cert(conf, privkey, privkey_len,
938 privkey_pass, privkey_pass_len, cert, cert_len) != ERR_OK) {
939 altcp_tls_free_config(conf);
940 return NULL;
941 }
942
943 return conf;
944}
945
946static struct altcp_tls_config *
947altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth)
948{
949 int ret;
950 struct altcp_tls_config *conf = altcp_tls_create_config(0, (is_2wayauth) ? 1 : 0, (is_2wayauth) ? 1 : 0, ca != NULL);
951 if (conf == NULL) {
952 return NULL;
953 }
954
955 /* Initialize the CA certificate if provided
956 * CA certificate is optional (to save memory) but recommended for production environment
957 * Without CA certificate, connection will be prone to man-in-the-middle attacks */
958 if (ca) {
959 mbedtls_x509_crt_init(conf->ca);
960 ret = mbedtls_x509_crt_parse(conf->ca, ca, ca_len);
961 if (ret != 0) {
962 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse ca failed: %d 0x%x\n", ret, -1*ret));
963 altcp_tls_free_config(conf);
964 return NULL;
965 }
966
967 mbedtls_ssl_conf_ca_chain(&conf->conf, conf->ca, NULL);
968 }
969 return conf;
970}
971
972struct altcp_tls_config *
973altcp_tls_create_config_client(const u8_t *ca, size_t ca_len)
974{
975 return altcp_tls_create_config_client_common(ca, ca_len, 0);
976}
977
978struct altcp_tls_config *
979altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len,
980 const u8_t *privkey_pass, size_t privkey_pass_len,
981 const u8_t *cert, size_t cert_len)
982{
983 int ret;
984 struct altcp_tls_config *conf;
985
986 if (!cert || !privkey) {
987 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("altcp_tls_create_config_client_2wayauth: certificate and priv key required\n"));
988 return NULL;
989 }
990
991 conf = altcp_tls_create_config_client_common(ca, ca_len, 1);
992 if (conf == NULL) {
993 return NULL;
994 }
995
996 /* Initialize the client certificate and corresponding private key */
997 mbedtls_x509_crt_init(conf->cert);
998 ret = mbedtls_x509_crt_parse(conf->cert, cert, cert_len);
999 if (ret != 0) {
1000 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse cert failed: %d 0x%x\n", ret, -1*ret));
1001 altcp_tls_free_config(conf);
1002 return NULL;
1003 }
1004
1005 mbedtls_pk_init(conf->pkey);
1006 ret = mbedtls_pk_parse_key(conf->pkey, privkey, privkey_len, privkey_pass, privkey_pass_len);
1007 if (ret != 0) {
1008 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_key failed: %d 0x%x\n", ret, -1*ret));
1009 altcp_tls_free_config(conf);
1010 return NULL;
1011 }
1012
1013 ret = mbedtls_ssl_conf_own_cert(&conf->conf, conf->cert, conf->pkey);
1014 if (ret != 0) {
1015 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d 0x%x\n", ret, -1*ret));
1016 altcp_tls_free_config(conf);
1017 return NULL;
1018 }
1019
1020 return conf;
1021}
1022
1023int
1024altcp_tls_configure_alpn_protocols(struct altcp_tls_config *conf, const char **protos)
1025{
1026#if defined(MBEDTLS_SSL_ALPN)
1027 int ret = mbedtls_ssl_conf_alpn_protocols(&conf->conf, protos);
1028 if (ret != 0) {
1029 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_alpn_protocols failed: %d\n", ret));
1030 }
1031
1032 return ret;
1033#else
1034 return -1;
1035#endif
1036}
1037
1038void
1039altcp_tls_free_config(struct altcp_tls_config *conf)
1040{
1041 if (conf->pkey) {
1042 mbedtls_pk_free(conf->pkey);
1043 }
1044 if (conf->cert) {
1045 mbedtls_x509_crt_free(conf->cert);
1046 }
1047 if (conf->ca) {
1048 mbedtls_x509_crt_free(conf->ca);
1049 }
1050 mbedtls_ssl_config_free(&conf->conf);
1051 altcp_mbedtls_free_config(conf);
1052 altcp_mbedtls_unref_entropy();
1053}
1054
1055void
1056altcp_tls_free_entropy(void)
1057{
1059
1060 if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref == 0) {
1061 mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg);
1062 mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy);
1063 altcp_mbedtls_free_config(altcp_tls_entropy_rng);
1064 altcp_tls_entropy_rng = NULL;
1065 }
1066}
1067
1068/* "virtual" functions */
1069static void
1070altcp_mbedtls_set_poll(struct altcp_pcb *conn, u8_t interval)
1071{
1072 if (conn != NULL) {
1073 altcp_poll(conn->inner_conn, altcp_mbedtls_lower_poll, interval);
1074 }
1075}
1076
1077static void
1078altcp_mbedtls_recved(struct altcp_pcb *conn, u16_t len)
1079{
1080 u16_t lower_recved;
1081 altcp_mbedtls_state_t *state;
1082 if (conn == NULL) {
1083 return;
1084 }
1085 state = (altcp_mbedtls_state_t *)conn->state;
1086 if (state == NULL) {
1087 return;
1088 }
1089 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
1090 return;
1091 }
1092 lower_recved = len;
1093 if (lower_recved > state->rx_passed_unrecved) {
1094 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("bogus recved count (len > state->rx_passed_unrecved / %d / %d)\n",
1095 len, state->rx_passed_unrecved));
1096 lower_recved = (u16_t)state->rx_passed_unrecved;
1097 }
1098 state->rx_passed_unrecved -= lower_recved;
1099
1100 altcp_recved(conn->inner_conn, lower_recved);
1101}
1102
1103static err_t
1104altcp_mbedtls_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
1105{
1106 if (conn == NULL) {
1107 return ERR_VAL;
1108 }
1109 conn->connected = connected;
1110 return altcp_connect(conn->inner_conn, ipaddr, port, altcp_mbedtls_lower_connected);
1111}
1112
1113static struct altcp_pcb *
1114altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
1115{
1116 struct altcp_pcb *lpcb;
1117 if (conn == NULL) {
1118 return NULL;
1119 }
1120 lpcb = altcp_listen_with_backlog_and_err(conn->inner_conn, backlog, err);
1121 if (lpcb != NULL) {
1122 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
1123 /* Free members of the ssl context (not used on listening pcb). This
1124 includes freeing input/output buffers, so saves ~32KByte by default */
1125 mbedtls_ssl_free(&state->ssl_context);
1126
1127 conn->inner_conn = lpcb;
1128 altcp_accept(lpcb, altcp_mbedtls_lower_accept);
1129 return conn;
1130 }
1131 return NULL;
1132}
1133
1134static void
1135altcp_mbedtls_abort(struct altcp_pcb *conn)
1136{
1137 if (conn != NULL) {
1138 altcp_abort(conn->inner_conn);
1139 }
1140}
1141
1142static err_t
1143altcp_mbedtls_close(struct altcp_pcb *conn)
1144{
1145 struct altcp_pcb *inner_conn;
1146 if (conn == NULL) {
1147 return ERR_VAL;
1148 }
1149 inner_conn = conn->inner_conn;
1150 if (inner_conn) {
1151 err_t err;
1152 altcp_poll_fn oldpoll = inner_conn->poll;
1153 altcp_mbedtls_remove_callbacks(conn->inner_conn);
1154 err = altcp_close(conn->inner_conn);
1155 if (err != ERR_OK) {
1156 /* not closed, set up all callbacks again */
1157 altcp_mbedtls_setup_callbacks(conn, inner_conn);
1158 /* poll callback is not included in the above */
1159 altcp_poll(inner_conn, oldpoll, inner_conn->pollinterval);
1160 return err;
1161 }
1162 conn->inner_conn = NULL;
1163 }
1164 altcp_free(conn);
1165 return ERR_OK;
1166}
1167
1171static u16_t
1172altcp_mbedtls_sndbuf(struct altcp_pcb *conn)
1173{
1174 if (conn) {
1175 altcp_mbedtls_state_t *state;
1176 state = (altcp_mbedtls_state_t*)conn->state;
1177 if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
1178 return 0;
1179 }
1180 if (conn->inner_conn) {
1181 u16_t sndbuf = altcp_sndbuf(conn->inner_conn);
1182 /* Take care of record header, IV, AuthTag */
1183 int ssl_expan = mbedtls_ssl_get_record_expansion(&state->ssl_context);
1184 if (ssl_expan > 0) {
1185 size_t ssl_added = (u16_t)LWIP_MIN(ssl_expan, 0xFFFF);
1186 /* internal sndbuf smaller than our offset */
1187 if (ssl_added < sndbuf) {
1188 size_t max_len = 0xFFFF;
1189 size_t ret;
1190#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
1191 /* @todo: adjust ssl_added to real value related to negotiated cipher */
1192 size_t max_frag_len = mbedtls_ssl_get_max_frag_len(&state->ssl_context);
1193 max_len = LWIP_MIN(max_frag_len, max_len);
1194#endif
1195 /* Adjust sndbuf of inner_conn with what added by SSL */
1196 ret = LWIP_MIN(sndbuf - ssl_added, max_len);
1197 LWIP_ASSERT("sndbuf overflow", ret <= 0xFFFF);
1198 return (u16_t)ret;
1199 }
1200 }
1201 }
1202 }
1203 /* fallback: use sendbuf of the inner connection */
1204 return altcp_default_sndbuf(conn);
1205}
1206
1210static err_t
1211altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
1212{
1213 int ret;
1214 altcp_mbedtls_state_t *state;
1215
1216 LWIP_UNUSED_ARG(apiflags);
1217
1218 if (conn == NULL) {
1219 return ERR_VAL;
1220 }
1221
1222 state = (altcp_mbedtls_state_t *)conn->state;
1223 if (state == NULL) {
1224 /* @todo: which error? */
1225 return ERR_ARG;
1226 }
1227 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
1228 /* @todo: which error? */
1229 return ERR_VAL;
1230 }
1231
1232 /* HACK: if there is something left to send, try to flush it and only
1233 allow sending more if this succeeded (this is a hack because neither
1234 returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */
1235 if (state->ssl_context.out_left) {
1236 mbedtls_ssl_flush_output(&state->ssl_context);
1237 if (state->ssl_context.out_left) {
1238 return ERR_MEM;
1239 }
1240 }
1241 ret = mbedtls_ssl_write(&state->ssl_context, (const unsigned char *)dataptr, len);
1242 /* try to send data... */
1243 altcp_output(conn->inner_conn);
1244 if (ret >= 0) {
1245 if (ret == len) {
1246 /* update application sent counter */
1247 state->overhead_bytes_adjust -= ret;
1248 return ERR_OK;
1249 } else {
1250 /* @todo/@fixme: assumption: either everything sent or error */
1251 LWIP_ASSERT("ret <= 0", 0);
1252 return ERR_MEM;
1253 }
1254 } else {
1256 /* @todo: convert error to err_t */
1257 return ERR_MEM;
1258 }
1259 LWIP_ASSERT("unhandled error", 0);
1260 return ERR_VAL;
1261 }
1262}
1263
1268static int
1269altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size)
1270{
1271 struct altcp_pcb *conn = (struct altcp_pcb *) ctx;
1272 altcp_mbedtls_state_t *state;
1273 int written = 0;
1274 size_t size_left = size;
1275 u8_t apiflags = TCP_WRITE_FLAG_COPY;
1276
1277 LWIP_ASSERT("conn != NULL", conn != NULL);
1278 if ((conn == NULL) || (conn->inner_conn == NULL)) {
1280 }
1281 state = (altcp_mbedtls_state_t *)conn->state;
1282 LWIP_ASSERT("state != NULL", state != NULL);
1283
1284 while (size_left) {
1285 u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF);
1286 err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags);
1287 if (err == ERR_OK) {
1288 written += write_len;
1289 size_left -= write_len;
1290 state->overhead_bytes_adjust += write_len;
1291 } else if (err == ERR_MEM) {
1292 if (written) {
1293 return written;
1294 }
1295 return 0; /* MBEDTLS_ERR_SSL_WANT_WRITE; */
1296 } else {
1297 LWIP_ASSERT("tls_write, tcp_write: err != ERR MEM", 0);
1298 /* @todo: return MBEDTLS_ERR_NET_CONN_RESET or MBEDTLS_ERR_NET_SEND_FAILED */
1300 }
1301 }
1302 return written;
1303}
1304
1305static u16_t
1306altcp_mbedtls_mss(struct altcp_pcb *conn)
1307{
1308 if (conn == NULL) {
1309 return 0;
1310 }
1311 /* @todo: LWIP_MIN(mss, mbedtls_ssl_get_max_frag_len()) ? */
1312 return altcp_mss(conn->inner_conn);
1313}
1314
1315static void
1316altcp_mbedtls_dealloc(struct altcp_pcb *conn)
1317{
1318 /* clean up and free tls state */
1319 if (conn) {
1320 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
1321 if (state) {
1322 mbedtls_ssl_free(&state->ssl_context);
1323 state->flags = 0;
1324 if (state->rx) {
1325 /* free leftover (unhandled) rx pbufs */
1326 pbuf_free(state->rx);
1327 state->rx = NULL;
1328 }
1329 altcp_mbedtls_free(state->conf, state);
1330 conn->state = NULL;
1331 }
1332 }
1333}
1334
1335const struct altcp_functions altcp_mbedtls_functions = {
1336 altcp_mbedtls_set_poll,
1337 altcp_mbedtls_recved,
1338 altcp_default_bind,
1339 altcp_mbedtls_connect,
1340 altcp_mbedtls_listen,
1341 altcp_mbedtls_abort,
1342 altcp_mbedtls_close,
1343 altcp_default_shutdown,
1344 altcp_mbedtls_write,
1345 altcp_default_output,
1346 altcp_mbedtls_mss,
1347 altcp_mbedtls_sndbuf,
1348 altcp_default_sndqueuelen,
1349 altcp_default_nagle_disable,
1350 altcp_default_nagle_enable,
1351 altcp_default_nagle_disabled,
1352 altcp_default_setprio,
1353 altcp_mbedtls_dealloc,
1354 altcp_default_get_tcp_addrinfo,
1355 altcp_default_get_ip,
1356 altcp_default_get_port
1357#if LWIP_TCP_KEEPALIVE
1358 , altcp_default_keepalive_disable
1359 , altcp_default_keepalive_enable
1360#endif
1361#ifdef LWIP_DEBUG
1362 , altcp_default_dbg_get_tcp_state
1363#endif
1364};
1365
1366#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
1367#endif /* LWIP_ALTCP */
#define altcp_accept
Definition: altcp.h:169
#define altcp_write
Definition: altcp.h:187
#define altcp_output
Definition: altcp.h:188
#define altcp_poll_fn
Definition: altcp.h:156
#define altcp_mss
Definition: altcp.h:190
#define altcp_arg
Definition: altcp.h:168
#define altcp_connect
Definition: altcp.h:177
#define altcp_sndbuf
Definition: altcp.h:191
#define altcp_poll
Definition: altcp.h:172
#define altcp_sent
Definition: altcp.h:171
#define altcp_listen_with_backlog_and_err
Definition: altcp.h:179
#define altcp_err
Definition: altcp.h:173
#define altcp_recv
Definition: altcp.h:170
#define altcp_pcb
Definition: altcp.h:159
#define altcp_close
Definition: altcp.h:184
#define altcp_abort
Definition: altcp.h:183
#define altcp_connected_fn
Definition: altcp.h:153
#define altcp_recved
Definition: altcp.h:175
static int state
Definition: maze.c:121
Sample certificates and DHM parameters for testing.
This file contains definitions and functions for the CTR_DRBG pseudorandom generator.
#define LWIP_MIN(x, y)
Definition: def.h:66
#define NULL
Definition: types.h:112
static const WCHAR ca[]
Definition: main.c:457
USHORT port
Definition: uri.c:228
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
Entropy accumulator implementation.
#define ERR_MEM
Definition: fontsub.h:52
int connected
Definition: main.c:61
GLint level
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
s8_t err_t
Definition: err.h:96
@ ERR_OK
Definition: err.h:55
@ ERR_CLSD
Definition: err.h:86
@ ERR_VAL
Definition: err.h:67
@ ERR_ARG
Definition: err.h:88
@ ERR_ABRT
Definition: err.h:82
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define PBUF_POOL_BUFSIZE
Definition: opt.h:1599
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:402
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:855
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1058
@ PBUF_POOL
Definition: pbuf.h:167
@ PBUF_RAW
Definition: pbuf.h:111
void mbedtls_x509_crt_init(mbedtls_x509_crt *crt)
Initialize a certificate (chain)
int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen)
Parse one DER-encoded or one or more concatenated PEM-encoded certificates and add them to the chaine...
void mbedtls_x509_crt_free(mbedtls_x509_crt *crt)
Unallocate all certificate data.
#define stdout
Definition: stdio.h:99
#define TCP_WND
Definition: lwipopts.h:48
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
int const JOCTET * dataptr
Definition: jpeglib.h:1031
if(dx< 0)
Definition: linetemp.h:194
Buffer-based memory allocator.
static BYTE cert[]
Definition: msg.c:1374
Network sockets abstraction layer to integrate Mbed TLS into a BSD-style sockets API.
#define MBEDTLS_ERR_NET_CONN_RESET
Definition: net_sockets.h:86
#define MBEDTLS_ERR_NET_INVALID_CONTEXT
Definition: net_sockets.h:89
#define MBEDTLS_ERR_NET_SEND_FAILED
Definition: net_sockets.h:85
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen)
Parse a private key in PEM or DER format.
void mbedtls_pk_init(mbedtls_pk_context *ctx)
Initialize a mbedtls_pk_context (as NONE).
void mbedtls_pk_free(mbedtls_pk_context *ctx)
Free the components of a mbedtls_pk_context.
#define err(...)
const WCHAR * str
#define mbedtls_ssl_free
#define mbedtls_ssl_get_max_frag_len
#define mbedtls_ssl_init
#define mbedtls_ctr_drbg_seed
#define mbedtls_ctr_drbg_random
#define mbedtls_entropy_free
#define mbedtls_ctr_drbg_init
#define mbedtls_entropy_init
#define mbedtls_ssl_conf_authmode
#define mbedtls_ssl_write
#define mbedtls_ssl_config_defaults
#define mbedtls_ssl_setup
#define mbedtls_ssl_set_bio
#define mbedtls_ssl_conf_rng
#define mbedtls_ssl_config_free
#define mbedtls_ssl_handshake
#define mbedtls_ctr_drbg_free
#define mbedtls_ssl_read
#define mbedtls_ssl_conf_dbg
#define mbedtls_ssl_config_init
Functions for controlling and providing debug output from the library.
Error to string translation.
This file contains the definitions and functions of the Mbed TLS platform abstraction layer.
SSL/TLS functions.
#define MBEDTLS_SSL_IS_CLIENT
Definition: ssl.h:179
#define MBEDTLS_SSL_MAX_CONTENT_LEN
This macro is invoked by the library when an invalid parameter is detected that is only checked with ...
Definition: ssl.h:265
int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key)
Set own certificate chain and private key.
#define MBEDTLS_ERR_SSL_WANT_WRITE
Definition: ssl.h:141
#define MBEDTLS_ERR_SSL_WANT_READ
Definition: ssl.h:140
#define MBEDTLS_SSL_IS_SERVER
Definition: ssl.h:180
void mbedtls_ssl_session_init(mbedtls_ssl_session *session)
Initialize SSL session structure.
void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl)
Set the data required to verify peer certificate.
int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session)
Request resumption of session (client-side only) Session data is copied from presented session struct...
int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl)
Return the (maximum) number of bytes added by the record layer: header + encryption/MAC overhead (inc...
void mbedtls_ssl_session_free(mbedtls_ssl_session *session)
Free referenced items in an SSL session including the peer certificate and clear memory.
#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY
Definition: ssl.h:112
#define MBEDTLS_SSL_TRANSPORT_STREAM
Definition: ssl.h:162
size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl)
Return the number of application data bytes remaining to be read from the current record.
int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session)
Save session in order to resume it later (client-side only) Session data is copied to presented sessi...
int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos)
Set the supported Application Layer Protocols.
#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT
Definition: ssl.h:143
#define MBEDTLS_SSL_PRESET_DEFAULT
Definition: ssl.h:228
SSL session cache implementation.
int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session)
Cache set callback implementation (Thread-safe if MBEDTLS_THREADING_C is enabled)
void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max)
Set the maximum number of cache entries (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session)
Cache get callback implementation (Thread-safe if MBEDTLS_THREADING_C is enabled)
Internal functions shared by the SSL modules.
int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl)
TLS server ticket callbacks implementation.
void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Initialize a ticket context. (Just make it ready for mbedtls_ssl_ticket_setup() or mbedtls_ssl_ticket...
int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, int(*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_cipher_type_t cipher, uint32_t lifetime)
Prepare context to be actually used.
mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write
Implementation of the ticket write callback.
Definition: ssl_ticket.h:147
mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse
Implementation of the ticket parse callback.
Definition: ssl_ticket.h:154
Definition: cache.c:49
Definition: fci.c:127
Definition: parser.c:49
The CTR_DRBG context structure.
Definition: ctr_drbg.h:195
Entropy context structure.
Definition: entropy.h:149
Public key container.
Definition: pk.h:156
Context for session ticket handling functions.
Definition: ssl_ticket.h:90
Definition: mem.c:349
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
Definition: send.c:48
X.509 generic defines and structures.