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