BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 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 * - define ALTCP_MBEDTLS_RNG_FN to a custom GOOD rng function returning 0 on success:
44 * int my_rng_fn(void *ctx, unsigned char *buffer , size_t len)
45 * - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing
46 * GOOD custom entropy
47 *
48 * Missing things / @todo:
49 * - RX data is acknowledged after receiving (tcp_recved is called when enqueueing
50 * the pbuf for mbedTLS receive, not when processed by mbedTLS or the inner
51 * connection; altcp_recved() from inner connection does nothing)
52 * - Client connections starting with 'connect()' are not handled yet...
53 * - some unhandled things are caught by LWIP_ASSERTs...
54 */
55  
56 #include "lwip/opt.h"
57  
58 #if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
59  
60 #include "lwip/apps/altcp_tls_mbedtls_opts.h"
61  
62 #if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS
63  
64 #include "lwip/altcp.h"
65 #include "lwip/altcp_tls.h"
66 #include "lwip/priv/altcp_priv.h"
67  
68 #include "altcp_tls_mbedtls_structs.h"
69 #include "altcp_tls_mbedtls_mem.h"
70  
71 /* @todo: which includes are really needed? */
72 #include "mbedtls/entropy.h"
73 #include "mbedtls/ctr_drbg.h"
74 #include "mbedtls/certs.h"
75 #include "mbedtls/x509.h"
76 #include "mbedtls/ssl.h"
77 #include "mbedtls/net.h"
78 #include "mbedtls/error.h"
79 #include "mbedtls/debug.h"
80 #include "mbedtls/platform.h"
81 #include "mbedtls/memory_buffer_alloc.h"
82 #include "mbedtls/ssl_cache.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  
95 /* Variable prototype, the actual declaration is at the end of this file
96 since it contains pointers to static functions declared here */
97 extern const struct altcp_functions altcp_mbedtls_functions;
98  
99 /** Our global mbedTLS configuration (server-specific, not connection-specific) */
100 struct altcp_tls_config {
101 mbedtls_ssl_config conf;
102 mbedtls_entropy_context entropy;
103 mbedtls_ctr_drbg_context ctr_drbg;
104 #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
105 /** Inter-connection cache for fast connection startup */
106 struct mbedtls_ssl_cache_context cache;
107 #endif
108 };
109  
110 static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err);
111 static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn);
112 static void altcp_mbedtls_dealloc(struct altcp_pcb *conn);
113 static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
114 static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
115 static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size);
116  
117  
118 /* callback functions from inner/lower connection: */
119  
120 /** Accept callback from lower connection (i.e. TCP)
121 * Allocate one of our structures, assign it to the new connection's 'state' and
122 * call the new connection's 'accepted' callback. If that succeeds, we wait
123 * to receive connection setup handshake bytes from the client.
124 */
125 static err_t
126 altcp_mbedtls_lower_accept(void *arg, struct altcp_pcb *accepted_conn, err_t err)
127 {
128 struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg;
129 if (listen_conn && listen_conn->state && listen_conn->accept) {
130 err_t setup_err;
131 altcp_mbedtls_state_t *listen_state = (altcp_mbedtls_state_t *)listen_conn->state;
132 /* create a new altcp_conn to pass to the next 'accept' callback */
133 struct altcp_pcb *new_conn = altcp_alloc();
134 if (new_conn == NULL) {
135 return ERR_MEM;
136 }
137 setup_err = altcp_mbedtls_setup(listen_state->conf, new_conn, accepted_conn);
138 if (setup_err != ERR_OK) {
139 altcp_free(new_conn);
140 return setup_err;
141 }
142 return listen_conn->accept(listen_conn->arg, new_conn, err);
143 }
144 return ERR_ARG;
145 }
146  
147 /** Connected callback from lower connection (i.e. TCP).
148 * Not really implemented/tested yet...
149 */
150 static err_t
151 altcp_mbedtls_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err)
152 {
153 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
154 if (conn && conn->state) {
155 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
156 /* upper connected is called when handshake is done */
157 if (err != ERR_OK) {
158 if (conn->connected) {
159 if (conn->connected(conn->arg, conn, err) == ERR_ABRT) {
160 return ERR_ABRT;
161 }
162 return ERR_OK;
163 }
164 }
165 return altcp_mbedtls_lower_recv_process(conn, (altcp_mbedtls_state_t *)conn->state);
166 }
167 return ERR_VAL;
168 }
169  
170 /* Call recved for possibly more than an u16_t */
171 static void
172 altcp_mbedtls_lower_recved(struct altcp_pcb *inner_conn, int recvd_cnt)
173 {
174 while (recvd_cnt > 0) {
175 u16_t recvd_part = (u16_t)LWIP_MIN(recvd_cnt, 0xFFFF);
176 altcp_recved(inner_conn, recvd_part);
177 recvd_cnt -= recvd_part;
178 }
179 }
180  
181 /** Recv callback from lower connection (i.e. TCP)
182 * This one mainly differs between connection setup/handshake (data is fed into mbedTLS only)
183 * and application phase (data is decoded by mbedTLS and passed on to the application).
184 */
185 static err_t
186 altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err)
187 {
188 altcp_mbedtls_state_t *state;
189 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
190  
191 LWIP_ASSERT("no err expected", err == ERR_OK);
192 LWIP_UNUSED_ARG(err);
193  
194 if (!conn) {
195 /* no connection given as arg? should not happen, but prevent pbuf/conn leaks */
196 if (p != NULL) {
197 pbuf_free(p);
198 }
199 altcp_close(inner_conn);
200 return ERR_CLSD;
201 }
202 state = (altcp_mbedtls_state_t *)conn->state;
203 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
204 if (!state) {
205 /* already closed */
206 if (p != NULL) {
207 pbuf_free(p);
208 }
209 altcp_close(inner_conn);
210 return ERR_CLSD;
211 }
212  
213 /* handle NULL pbuf (connection closed) */
214 if (p == NULL) {
215 /* remote host sent FIN, remember this (SSL state is destroyed
216 when both sides are closed only!) */
217 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED;
218 if ((state->flags & (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) ==
219 (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) {
220 /* need to notify upper layer (e.g. 'accept' called or 'connect' succeeded) */
221 if ((state->rx != NULL) || (state->rx_app != NULL)) {
222 /* this is a normal close (FIN) but we have unprocessed data, so delay the FIN */
223 altcp_mbedtls_handle_rx_appldata(conn, state);
224 return ERR_OK;
225 }
226 if (conn->recv) {
227 err_t local_err = conn->recv(conn->arg, conn, NULL, ERR_OK);
228 if (local_err == ERR_ABRT) {
229 return ERR_ABRT;
230 }
231 }
232 } else {
233 /* before connection setup is done: call 'err' */
234 if (conn->err) {
235 conn->err(conn->arg, ERR_CLSD);
236 }
237 }
238 altcp_close(conn);
239 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
240 if (conn->state && ((state->flags & ALTCP_MBEDTLS_FLAGS_CLOSED) == ALTCP_MBEDTLS_FLAGS_CLOSED)) {
241 altcp_mbedtls_dealloc(conn);
242 }
243 return ERR_OK;
244 }
245  
246 /* If we come here, the connection is in good state (handshake phase or application data phase).
247 Queue up the pbuf for processing as handshake data or application data. */
248 if (state->rx == NULL) {
249 state->rx = p;
250 } else {
251 LWIP_ASSERT("rx pbuf overflow", (int)p->tot_len + (int)p->len <= 0xFFFF);
252 pbuf_cat(state->rx, p);
253 }
254 return altcp_mbedtls_lower_recv_process(conn, state);
255 }
256  
257 static err_t
258 altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
259 {
260 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
261 /* handle connection setup (handshake not done) */
262 int ret = mbedtls_ssl_handshake(&state->ssl_context);
263 /* try to send data... */
264 altcp_output(conn->inner_conn);
265 if (state->bio_bytes_read) {
266 /* acknowledge all bytes read */
267 altcp_mbedtls_lower_recved(conn->inner_conn, state->bio_bytes_read);
268 state->bio_bytes_read = 0;
269 }
270  
271 if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
272 /* handshake not done, wait for more recv calls */
273 LWIP_ASSERT("in this state, the rx chain should be empty", state->rx == NULL);
274 return ERR_OK;
275 }
276 if (ret != 0) {
277 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret));
278 /* handshake failed, connection has to be closed */
279 conn->recv(conn->arg, conn, NULL, ERR_OK);
280 if (altcp_close(conn->inner_conn) != ERR_OK) {
281 altcp_abort(conn->inner_conn);
282 }
283 return ERR_OK;
284 }
285 /* If we come here, handshake succeeded. */
286 LWIP_ASSERT("state", state->bio_bytes_read == 0);
287 LWIP_ASSERT("state", state->bio_bytes_appl == 0);
288 state->flags |= ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE;
289 /* issue "connect" callback" to upper connection (this can only happen for active open) */
290 if (conn->connected) {
291 conn->connected(conn->arg, conn, ERR_OK);
292 }
293 if (state->rx == NULL) {
294 return ERR_OK;
295 }
296 }
297 /* handle application data */
298 return altcp_mbedtls_handle_rx_appldata(conn, state);
299 }
300  
301 /* Pass queued decoded rx data to application */
302 static err_t
303 altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
304 {
305 err_t err;
306 struct pbuf *buf;
307 LWIP_ASSERT("conn != NULL", conn != NULL);
308 LWIP_ASSERT("state != NULL", state != NULL);
309 buf = state->rx_app;
310 if (buf) {
311 if (conn->recv) {
312 u16_t tot_len = state->rx_app->tot_len;
313 /* this needs to be increased first because the 'recved' call may come nested */
314 state->rx_passed_unrecved += tot_len;
315 state->flags |= ALTCP_MBEDTLS_FLAGS_UPPER_CALLED;
316 err = conn->recv(conn->arg, conn, state->rx_app, ERR_OK);
317 if (err != ERR_OK) {
318 /* not received, leave the pbuf(s) queued (and decrease 'unrecved' again) */
319 state->rx_passed_unrecved -= tot_len;
320 LWIP_ASSERT("state->rx_passed_unrecved >= 0", state->rx_passed_unrecved >= 0);
321 if (state->rx_passed_unrecved < 0) {
322 state->rx_passed_unrecved = 0;
323 }
324 return err;
325 }
326 } else {
327 pbuf_free(buf);
328 }
329 state->rx_app = NULL;
330 } else if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
331 ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
332 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
333 if (conn->recv) {
334 err = conn->recv(conn->arg, conn, NULL, ERR_OK);
335 if (err == ERR_ABRT) {
336 return ERR_ABRT;
337 }
338 }
339 }
340  
341 return ERR_OK;
342 }
343  
344 /* Helper function that processes rx application data stored in rx pbuf chain */
345 static err_t
346 altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
347 {
348 int ret;
349 LWIP_ASSERT("state != NULL", state != NULL);
350 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
351 /* handshake not done yet */
352 return ERR_VAL;
353 }
354 do {
355 /* allocate a full-sized unchained PBUF_POOL: this is for RX! */
356 struct pbuf *buf = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
357 if (buf == NULL) {
358 /* We're short on pbufs, try again later from 'poll' or 'recv' callbacks.
359 @todo: close on excessive allocation failures or leave this up to upper conn? */
360 return ERR_OK;
361 }
362  
363 /* decrypt application data, this pulls encrypted RX data off state->rx pbuf chain */
364 ret = mbedtls_ssl_read(&state->ssl_context, (unsigned char *)buf->payload, PBUF_POOL_BUFSIZE);
365 if (ret < 0) {
366 if (ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) {
367 /* client is initiating a new connection using the same source port -> close connection or make handshake */
368 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("new connection on same source port\n"));
369 LWIP_ASSERT("TODO: new connection on same source port, close this connection", 0);
370 } else if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
371 if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
372 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was closed gracefully\n"));
373 } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
374 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was reset by peer\n"));
375 }
376 pbuf_free(buf);
377 return ERR_OK;
378 } else {
379 pbuf_free(buf);
380 return ERR_OK;
381 }
382 pbuf_free(buf);
383 altcp_abort(conn);
384 return ERR_ABRT;
385 } else {
386 err_t err;
387 if (ret) {
388 LWIP_ASSERT("bogus receive length", ret <= PBUF_POOL_BUFSIZE);
389 /* trim pool pbuf to actually decoded length */
390 pbuf_realloc(buf, (u16_t)ret);
391  
392 state->bio_bytes_appl += ret;
393 if (mbedtls_ssl_get_bytes_avail(&state->ssl_context) == 0) {
394 /* Record is done, now we know the share between application and protocol bytes
395 and can adjust the RX window by the protocol bytes.
396 The rest is 'recved' by the application calling our 'recved' fn. */
397 int overhead_bytes;
398 LWIP_ASSERT("bogus byte counts", state->bio_bytes_read > state->bio_bytes_appl);
399 overhead_bytes = state->bio_bytes_read - state->bio_bytes_appl;
400 altcp_mbedtls_lower_recved(conn->inner_conn, overhead_bytes);
401 state->bio_bytes_read = 0;
402 state->bio_bytes_appl = 0;
403 }
404  
405 if (state->rx_app == NULL) {
406 state->rx_app = buf;
407 } else {
408 pbuf_cat(state->rx_app, buf);
409 }
410 } else {
411 pbuf_free(buf);
412 buf = NULL;
413 }
414 err = altcp_mbedtls_pass_rx_data(conn, state);
415 if (err != ERR_OK) {
416 if (err == ERR_ABRT) {
417 /* recv callback needs to return this as the pcb is deallocated */
418 return ERR_ABRT;
419 }
420 /* we hide all other errors as we retry feeding the pbuf to the app later */
421 return ERR_OK;
422 }
423 }
424 } while (ret > 0);
425 return ERR_OK;
426 }
427  
428 /** Receive callback function called from mbedtls (set via mbedtls_ssl_set_bio)
429 * This function mainly copies data from pbufs and frees the pbufs after copying.
430 */
431 static int
432 altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len)
433 {
434 struct altcp_pcb *conn = (struct altcp_pcb *)ctx;
435 altcp_mbedtls_state_t *state;
436 struct pbuf *p;
437 u16_t ret;
438 u16_t copy_len;
439 err_t err;
440  
441 if ((conn == NULL) || (conn->state == NULL)) {
442 return MBEDTLS_ERR_NET_INVALID_CONTEXT;
443 }
444 state = (altcp_mbedtls_state_t *)conn->state;
445 p = state->rx;
446  
447 /* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */
448  
449 if ((p == NULL) || ((p->len == 0) && (p->next == NULL))) {
450 if (p) {
451 pbuf_free(p);
452 }
453 state->rx = NULL;
454 if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
455 ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
456 /* close queued but not passed up yet */
457 return 0;
458 }
459 return MBEDTLS_ERR_SSL_WANT_READ;
460 }
461 /* limit number of bytes again to copy from first pbuf in a chain only */
462 copy_len = (u16_t)LWIP_MIN(len, p->len);
463 /* copy the data */
464 ret = pbuf_copy_partial(p, buf, copy_len, 0);
465 LWIP_ASSERT("ret == copy_len", ret == copy_len);
466 /* hide the copied bytes from the pbuf */
467 err = pbuf_remove_header(p, ret);
468 LWIP_ASSERT("error", err == ERR_OK);
469 if (p->len == 0) {
470 /* the first pbuf has been fully read, free it */
471 state->rx = p->next;
472 p->next = NULL;
473 pbuf_free(p);
474 }
475  
476 state->bio_bytes_read += (int)ret;
477 return ret;
478 }
479  
480 /** Sent callback from lower connection (i.e. TCP)
481 * This only informs the upper layer to try to send more, not about
482 * the number of ACKed bytes.
483 */
484 static err_t
485 altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len)
486 {
487 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
488 LWIP_UNUSED_ARG(len);
489 if (conn) {
490 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
491 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
492 if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
493 /* @todo: do something here? */
494 return ERR_OK;
495 }
496 /* try to send more if we failed before */
497 mbedtls_ssl_flush_output(&state->ssl_context);
498 /* call upper sent with len==0 if the application already sent data */
499 if ((state->flags & ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT) && conn->sent) {
500 return conn->sent(conn->arg, conn, 0);
501 }
502 }
503 return ERR_OK;
504 }
505  
506 /** Poll callback from lower connection (i.e. TCP)
507 * Just pass this on to the application.
508 * @todo: retry sending?
509 */
510 static err_t
511 altcp_mbedtls_lower_poll(void *arg, struct altcp_pcb *inner_conn)
512 {
513 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
514 if (conn) {
515 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
516 /* check if there's unreceived rx data */
517 if (conn->state) {
518 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
519 /* try to send more if we failed before */
520 mbedtls_ssl_flush_output(&state->ssl_context);
521 if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) {
522 return ERR_ABRT;
523 }
524 }
525 if (conn->poll) {
526 return conn->poll(conn->arg, conn);
527 }
528 }
529 return ERR_OK;
530 }
531  
532 static void
533 altcp_mbedtls_lower_err(void *arg, err_t err)
534 {
535 struct altcp_pcb *conn = (struct altcp_pcb *)arg;
536 if (conn) {
537 conn->inner_conn = NULL; /* already freed */
538 if (conn->err) {
539 conn->err(conn->arg, err);
540 }
541 altcp_free(conn);
542 }
543 }
544  
545 /* setup functions */
546 static void
547 altcp_mbedtls_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
548 {
549 altcp_arg(inner_conn, conn);
550 altcp_recv(inner_conn, altcp_mbedtls_lower_recv);
551 altcp_sent(inner_conn, altcp_mbedtls_lower_sent);
552 altcp_err(inner_conn, altcp_mbedtls_lower_err);
553 /* tcp_poll is set when interval is set by application */
554 /* listen is set totally different :-) */
555 }
556  
557 static err_t
558 altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
559 {
560 int ret;
561 struct altcp_tls_config *config = (struct altcp_tls_config *)conf;
562 altcp_mbedtls_state_t *state;
563 if (!conf) {
564 return ERR_ARG;
565 }
566 /* allocate mbedtls context */
567 state = altcp_mbedtls_alloc(conf);
568 if (state == NULL) {
569 return ERR_MEM;
570 }
571 /* initialize mbedtls context: */
572 mbedtls_ssl_init(&state->ssl_context);
573 ret = mbedtls_ssl_setup(&state->ssl_context, &config->conf);
574 if (ret != 0) {
575 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_setup failed\n"));
576 /* @todo: convert 'ret' to err_t */
577 altcp_mbedtls_free(conf, state);
578 return ERR_MEM;
579 }
580 /* tell mbedtls about our I/O functions */
581 mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL);
582  
583 altcp_mbedtls_setup_callbacks(conn, inner_conn);
584 conn->inner_conn = inner_conn;
585 conn->fns = &altcp_mbedtls_functions;
586 conn->state = state;
587 return ERR_OK;
588 }
589  
590 struct altcp_pcb *
591 altcp_tls_new(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb)
592 {
593 struct altcp_pcb *ret;
594 if (inner_pcb == NULL) {
595 return NULL;
596 }
597 ret = altcp_alloc();
598 if (ret != NULL) {
599 if (altcp_mbedtls_setup(config, ret, inner_pcb) != ERR_OK) {
600 altcp_free(ret);
601 return NULL;
602 }
603 }
604 return ret;
605 }
606  
607 void *
608 altcp_tls_context(struct altcp_pcb *conn)
609 {
610 if (conn && conn->state) {
611 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
612 return &state->ssl_context;
613 }
614 return NULL;
615 }
616  
617 #if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF
618 static void
619 altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
620 {
621 LWIP_UNUSED_ARG(str);
622 LWIP_UNUSED_ARG(level);
623 LWIP_UNUSED_ARG(file);
624 LWIP_UNUSED_ARG(line);
625 LWIP_UNUSED_ARG(ctx);
626 /* @todo: output debug string :-) */
627 }
628 #endif
629  
630 #ifndef ALTCP_MBEDTLS_RNG_FN
631 /** ATTENTION: It is *really* important to *NOT* use this dummy RNG in production code!!!! */
632 static int
633 dummy_rng(void *ctx, unsigned char *buffer, size_t len)
634 {
635 static size_t ctr;
636 size_t i;
637 LWIP_UNUSED_ARG(ctx);
638 for (i = 0; i < len; i++) {
639 buffer[i] = (unsigned char)++ctr;
640 }
641 return 0;
642 }
643 #define ALTCP_MBEDTLS_RNG_FN dummy_rng
644 #endif /* ALTCP_MBEDTLS_RNG_FN */
645  
646 /** Create new TLS configuration
647 * ATTENTION: Server certificate and private key have to be added outside this function!
648 */
649 static struct altcp_tls_config *
650 altcp_tls_create_config(int is_server)
651 {
652 int ret;
653 struct altcp_tls_config *conf;
654  
655 altcp_mbedtls_mem_init();
656  
657 conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sizeof(struct altcp_tls_config));
658 if (conf == NULL) {
659 return NULL;
660 }
661  
662 mbedtls_ssl_config_init(&conf->conf);
663 mbedtls_entropy_init(&conf->entropy);
664 mbedtls_ctr_drbg_init(&conf->ctr_drbg);
665  
666 /* Seed the RNG */
667 ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN);
668 if (ret != 0) {
669 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret));
670 altcp_mbedtls_free_config(conf);
671 return NULL;
672 }
673  
674 /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */
675 ret = mbedtls_ssl_config_defaults(&conf->conf, is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
676 MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
677 if (ret != 0) {
678 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret));
679 altcp_mbedtls_free_config(conf);
680 return NULL;
681 }
682 mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
683  
684 mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg);
685 #if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF
686 mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout);
687 #endif
688 #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
689 mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
690 mbedtls_ssl_cache_set_timeout(&conf->cache, 30);
691 mbedtls_ssl_cache_set_max_entries(&conf->cache, 30);
692 #endif
693  
694 return conf;
695 }
696  
697 /** Create new TLS configuration
698 * This is a suboptimal version that gets the encrypted private key and its password,
699 * as well as the server certificate.
700 */
701 struct altcp_tls_config *
702 altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
703 const u8_t *privkey_pass, size_t privkey_pass_len,
704 const u8_t *cert, size_t cert_len)
705 {
706 int ret;
707 static mbedtls_x509_crt srvcert;
708 static mbedtls_pk_context pkey;
709 struct altcp_tls_config *conf = altcp_tls_create_config(1);
710 if (conf == NULL) {
711 return NULL;
712 }
713  
714 mbedtls_x509_crt_init(&srvcert);
715 mbedtls_pk_init(&pkey);
716  
717 /* Load the certificates and private key */
718 ret = mbedtls_x509_crt_parse(&srvcert, cert, cert_len);
719 if (ret != 0) {
720 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret));
721 altcp_mbedtls_free_config(conf);
722 return NULL;
723 }
724  
725 ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len);
726 if (ret != 0) {
727 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret));
728 altcp_mbedtls_free_config(conf);
729 return NULL;
730 }
731  
732 mbedtls_ssl_conf_ca_chain(&conf->conf, srvcert.next, NULL);
733 ret = mbedtls_ssl_conf_own_cert(&conf->conf, &srvcert, &pkey);
734 if (ret != 0) {
735 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret));
736 altcp_mbedtls_free_config(conf);
737 return NULL;
738 }
739 return conf;
740 }
741  
742 struct altcp_tls_config *
743 altcp_tls_create_config_client(const u8_t *cert, size_t cert_len)
744 {
745 int ret;
746 static mbedtls_x509_crt acc_cert;
747 struct altcp_tls_config *conf = altcp_tls_create_config(0);
748 if (conf == NULL) {
749 return NULL;
750 }
751  
752 mbedtls_x509_crt_init(&acc_cert);
753  
754 /* Load the certificates */
755 ret = mbedtls_x509_crt_parse(&acc_cert, cert, cert_len);
756 if (ret != 0) {
757 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d", ret));
758 altcp_mbedtls_free_config(conf);
759 return NULL;
760 }
761  
762 mbedtls_ssl_conf_ca_chain(&conf->conf, &acc_cert, NULL);
763 return conf;
764 }
765  
766 void
767 altcp_tls_free_config(struct altcp_tls_config *conf)
768 {
769 altcp_mbedtls_free_config(conf);
770 }
771  
772 /* "virtual" functions */
773 static void
774 altcp_mbedtls_set_poll(struct altcp_pcb *conn, u8_t interval)
775 {
776 if (conn != NULL) {
777 altcp_poll(conn->inner_conn, altcp_mbedtls_lower_poll, interval);
778 }
779 }
780  
781 static void
782 altcp_mbedtls_recved(struct altcp_pcb *conn, u16_t len)
783 {
784 u16_t lower_recved;
785 altcp_mbedtls_state_t *state;
786 if (conn == NULL) {
787 return;
788 }
789 state = (altcp_mbedtls_state_t *)conn->state;
790 if (state == NULL) {
791 return;
792 }
793 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
794 return;
795 }
796 lower_recved = len;
797 if (lower_recved > state->rx_passed_unrecved) {
798 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("bogus recved count (len > state->rx_passed_unrecved / %d / %d)",
799 len, state->rx_passed_unrecved));
800 lower_recved = (u16_t)state->rx_passed_unrecved;
801 }
802 state->rx_passed_unrecved -= lower_recved;
803  
804 altcp_recved(conn->inner_conn, lower_recved);
805 }
806  
807 static err_t
808 altcp_mbedtls_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
809 {
810 if (conn == NULL) {
811 return ERR_VAL;
812 }
813 conn->connected = connected;
814 return altcp_connect(conn->inner_conn, ipaddr, port, altcp_mbedtls_lower_connected);
815 }
816  
817 static struct altcp_pcb *
818 altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
819 {
820 struct altcp_pcb *lpcb;
821 if (conn == NULL) {
822 return NULL;
823 }
824 lpcb = altcp_listen_with_backlog_and_err(conn->inner_conn, backlog, err);
825 if (lpcb != NULL) {
826 conn->inner_conn = lpcb;
827 altcp_accept(lpcb, altcp_mbedtls_lower_accept);
828 return conn;
829 }
830 return NULL;
831 }
832  
833 static void
834 altcp_mbedtls_abort(struct altcp_pcb *conn)
835 {
836 if (conn != NULL) {
837 altcp_abort(conn->inner_conn);
838 }
839 }
840  
841 static err_t
842 altcp_mbedtls_close(struct altcp_pcb *conn)
843 {
844 altcp_mbedtls_state_t *state;
845 if (conn == NULL) {
846 return ERR_VAL;
847 }
848 state = (altcp_mbedtls_state_t *)conn->state;
849 if (state != NULL) {
850 state->flags |= ALTCP_MBEDTLS_FLAGS_TX_CLOSED;
851 if (state->flags & ALTCP_MBEDTLS_FLAGS_RX_CLOSED) {
852 altcp_mbedtls_dealloc(conn);
853 }
854 }
855 return altcp_close(conn->inner_conn);
856 }
857  
858 /** Write data to a TLS connection. Calls into mbedTLS, which in turn calls into
859 * @ref altcp_mbedtls_bio_send() to send the encrypted data
860 */
861 static err_t
862 altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
863 {
864 int ret;
865 altcp_mbedtls_state_t *state;
866  
867 LWIP_UNUSED_ARG(apiflags);
868  
869 if (conn == NULL) {
870 return ERR_VAL;
871 }
872  
873 state = (altcp_mbedtls_state_t *)conn->state;
874 if (state == NULL) {
875 /* @todo: which error? */
876 return ERR_CLSD;
877 }
878 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
879 /* @todo: which error? */
880 return ERR_VAL;
881 }
882  
883 /* HACK: if thre is something left to send, try to flush it and only
884 allow sending more if this succeeded (this is a hack because neither
885 returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */
886 if (state->ssl_context.out_left) {
887 mbedtls_ssl_flush_output(&state->ssl_context);
888 if (state->ssl_context.out_left) {
889 return ERR_MEM;
890 }
891 }
892 ret = mbedtls_ssl_write(&state->ssl_context, (const unsigned char *)dataptr, len);
893 /* try to send data... */
894 altcp_output(conn->inner_conn);
895 if (ret >= 0) {
896 if (ret == len) {
897 state->flags |= ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT;
898 return ERR_OK;
899 } else {
900 /* @todo/@fixme: assumption: either everything sent or error */
901 LWIP_ASSERT("ret <= 0", 0);
902 return ERR_MEM;
903 }
904 } else {
905 if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
906 /* @todo: convert error to err_t */
907 return ERR_MEM;
908 }
909 LWIP_ASSERT("unhandled error", 0);
910 return ERR_VAL;
911 }
912 }
913  
914 /** Send callback function called from mbedtls (set via mbedtls_ssl_set_bio)
915 * This function is either called during handshake or when sending application
916 * data via @ref altcp_mbedtls_write (or altcp_write)
917 */
918 static int
919 altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size)
920 {
921 struct altcp_pcb *conn = (struct altcp_pcb *) ctx;
922 int written = 0;
923 size_t size_left = size;
924 u8_t apiflags = TCP_WRITE_FLAG_COPY;
925  
926 LWIP_ASSERT("conn != NULL", conn != NULL);
927 if ((conn == NULL) || (conn->inner_conn == NULL)) {
928 return MBEDTLS_ERR_NET_INVALID_CONTEXT;
929 }
930  
931 while (size_left) {
932 u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF);
933 err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags);
934 if (err == ERR_OK) {
935 written += write_len;
936 size_left -= write_len;
937 } else if (err == ERR_MEM) {
938 if (written) {
939 return written;
940 }
941 return 0; /* MBEDTLS_ERR_SSL_WANT_WRITE; */
942 } else {
943 LWIP_ASSERT("tls_write, tcp_write: err != ERR MEM", 0);
944 /* @todo: return MBEDTLS_ERR_NET_CONN_RESET or MBEDTLS_ERR_NET_SEND_FAILED */
945 return MBEDTLS_ERR_NET_SEND_FAILED;
946 }
947 }
948 return written;
949 }
950  
951 static u16_t
952 altcp_mbedtls_mss(struct altcp_pcb *conn)
953 {
954 if (conn == NULL) {
955 return 0;
956 }
957 /* @todo: LWIP_MIN(mss, mbedtls_ssl_get_max_frag_len()) ? */
958 return altcp_mss(conn->inner_conn);
959 }
960  
961 static void
962 altcp_mbedtls_dealloc(struct altcp_pcb *conn)
963 {
964 /* clean up and free tls state */
965 if (conn) {
966 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
967 if (state) {
968 mbedtls_ssl_free(&state->ssl_context);
969 state->flags = 0;
970 altcp_mbedtls_free(state->conf, state);
971 conn->state = NULL;
972 }
973 if (conn->inner_conn) {
974 altcp_free(conn->inner_conn);
975 conn->inner_conn = NULL;
976 }
977 }
978 }
979  
980 const struct altcp_functions altcp_mbedtls_functions = {
981 altcp_mbedtls_set_poll,
982 altcp_mbedtls_recved,
983 altcp_default_bind,
984 altcp_mbedtls_connect,
985 altcp_mbedtls_listen,
986 altcp_mbedtls_abort,
987 altcp_mbedtls_close,
988 altcp_default_shutdown,
989 altcp_mbedtls_write,
990 altcp_default_output,
991 altcp_mbedtls_mss,
992 altcp_default_sndbuf,
993 altcp_default_sndqueuelen,
994 altcp_default_nagle_disable,
995 altcp_default_nagle_enable,
996 altcp_default_nagle_disabled,
997 altcp_default_setprio,
998 altcp_mbedtls_dealloc,
999 altcp_default_get_tcp_addrinfo,
1000 altcp_default_get_ip,
1001 altcp_default_get_port
1002 #ifdef LWIP_DEBUG
1003 , altcp_default_dbg_get_tcp_state
1004 #endif
1005 };
1006  
1007 #endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
1008 #endif /* LWIP_ALTCP */