xref: /btstack/3rd-party/lwip/core/src/apps/altcp_tls/altcp_tls_mbedtls.c (revision 97dc5e692c7d94a280158af58036a0efee5b0e56)
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 <[email protected]>
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   u8_t cert_count;
102   u8_t cert_max;
103   u8_t pkey_count;
104   u8_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,u8_t cert_count,u8_t pkey_count,int have_ca)671 altcp_tls_create_config(int is_server, u8_t cert_count, u8_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(u8_t cert_count)788 struct altcp_tls_config *altcp_tls_create_config_server(u8_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 int
altcp_tls_configure_alpn_protocols(struct altcp_tls_config * conf,const char ** protos)949 altcp_tls_configure_alpn_protocols(struct altcp_tls_config *conf, const char **protos)
950 {
951 #if defined(MBEDTLS_SSL_ALPN)
952   int ret = mbedtls_ssl_conf_alpn_protocols(&conf->conf, protos);
953   if (ret != 0) {
954     LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_alpn_protocols failed: %d\n", ret));
955   }
956 
957   return ret;
958 #else
959   return -1;
960 #endif
961 }
962 
963 void
altcp_tls_free_config(struct altcp_tls_config * conf)964 altcp_tls_free_config(struct altcp_tls_config *conf)
965 {
966   if (conf->pkey) {
967     mbedtls_pk_free(conf->pkey);
968   }
969   if (conf->cert) {
970     mbedtls_x509_crt_free(conf->cert);
971   }
972   if (conf->ca) {
973     mbedtls_x509_crt_free(conf->ca);
974   }
975   altcp_mbedtls_free_config(conf);
976   if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref)
977       altcp_tls_entropy_rng->ref--;
978 }
979 
980 void
altcp_tls_free_entropy(void)981 altcp_tls_free_entropy(void)
982 {
983   if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref == 0) {
984     mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg);
985     mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy);
986     altcp_mbedtls_free_config(altcp_tls_entropy_rng);
987     altcp_tls_entropy_rng = NULL;
988   }
989 }
990 
991 /* "virtual" functions */
992 static void
altcp_mbedtls_set_poll(struct altcp_pcb * conn,u8_t interval)993 altcp_mbedtls_set_poll(struct altcp_pcb *conn, u8_t interval)
994 {
995   if (conn != NULL) {
996     altcp_poll(conn->inner_conn, altcp_mbedtls_lower_poll, interval);
997   }
998 }
999 
1000 static void
altcp_mbedtls_recved(struct altcp_pcb * conn,u16_t len)1001 altcp_mbedtls_recved(struct altcp_pcb *conn, u16_t len)
1002 {
1003   u16_t lower_recved;
1004   altcp_mbedtls_state_t *state;
1005   if (conn == NULL) {
1006     return;
1007   }
1008   state = (altcp_mbedtls_state_t *)conn->state;
1009   if (state == NULL) {
1010     return;
1011   }
1012   if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
1013     return;
1014   }
1015   lower_recved = len;
1016   if (lower_recved > state->rx_passed_unrecved) {
1017     LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("bogus recved count (len > state->rx_passed_unrecved / %d / %d)",
1018                                       len, state->rx_passed_unrecved));
1019     lower_recved = (u16_t)state->rx_passed_unrecved;
1020   }
1021   state->rx_passed_unrecved -= lower_recved;
1022 
1023   altcp_recved(conn->inner_conn, lower_recved);
1024 }
1025 
1026 static err_t
altcp_mbedtls_connect(struct altcp_pcb * conn,const ip_addr_t * ipaddr,u16_t port,altcp_connected_fn connected)1027 altcp_mbedtls_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
1028 {
1029   if (conn == NULL) {
1030     return ERR_VAL;
1031   }
1032   conn->connected = connected;
1033   return altcp_connect(conn->inner_conn, ipaddr, port, altcp_mbedtls_lower_connected);
1034 }
1035 
1036 static struct altcp_pcb *
altcp_mbedtls_listen(struct altcp_pcb * conn,u8_t backlog,err_t * err)1037 altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
1038 {
1039   struct altcp_pcb *lpcb;
1040   if (conn == NULL) {
1041     return NULL;
1042   }
1043   lpcb = altcp_listen_with_backlog_and_err(conn->inner_conn, backlog, err);
1044   if (lpcb != NULL) {
1045     altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
1046     /* Free members of the ssl context (not used on listening pcb). This
1047        includes freeing input/output buffers, so saves ~32KByte by default */
1048     mbedtls_ssl_free(&state->ssl_context);
1049 
1050     conn->inner_conn = lpcb;
1051     altcp_accept(lpcb, altcp_mbedtls_lower_accept);
1052     return conn;
1053   }
1054   return NULL;
1055 }
1056 
1057 static void
altcp_mbedtls_abort(struct altcp_pcb * conn)1058 altcp_mbedtls_abort(struct altcp_pcb *conn)
1059 {
1060   if (conn != NULL) {
1061     altcp_abort(conn->inner_conn);
1062   }
1063 }
1064 
1065 static err_t
altcp_mbedtls_close(struct altcp_pcb * conn)1066 altcp_mbedtls_close(struct altcp_pcb *conn)
1067 {
1068   struct altcp_pcb *inner_conn;
1069   if (conn == NULL) {
1070     return ERR_VAL;
1071   }
1072   inner_conn = conn->inner_conn;
1073   if (inner_conn) {
1074     err_t err;
1075     altcp_poll_fn oldpoll = inner_conn->poll;
1076     altcp_mbedtls_remove_callbacks(conn->inner_conn);
1077     err = altcp_close(conn->inner_conn);
1078     if (err != ERR_OK) {
1079       /* not closed, set up all callbacks again */
1080       altcp_mbedtls_setup_callbacks(conn, inner_conn);
1081       /* poll callback is not included in the above */
1082       altcp_poll(inner_conn, oldpoll, inner_conn->pollinterval);
1083       return err;
1084     }
1085     conn->inner_conn = NULL;
1086   }
1087   altcp_free(conn);
1088   return ERR_OK;
1089 }
1090 
1091 /** Allow caller of altcp_write() to limit to negotiated chunk size
1092  *  or remaining sndbuf space of inner_conn.
1093  */
1094 static u16_t
altcp_mbedtls_sndbuf(struct altcp_pcb * conn)1095 altcp_mbedtls_sndbuf(struct altcp_pcb *conn)
1096 {
1097   if (conn) {
1098     altcp_mbedtls_state_t *state;
1099     state = (altcp_mbedtls_state_t*)conn->state;
1100     if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
1101       return 0;
1102     }
1103     if (conn->inner_conn) {
1104       u16_t sndbuf = altcp_sndbuf(conn->inner_conn);
1105       /* Take care of record header, IV, AuthTag */
1106       int ssl_expan = mbedtls_ssl_get_record_expansion(&state->ssl_context);
1107       if (ssl_expan > 0) {
1108         size_t ssl_added = (u16_t)LWIP_MIN(ssl_expan, 0xFFFF);
1109         /* internal sndbuf smaller than our offset */
1110         if (ssl_added < sndbuf) {
1111           size_t max_len = 0xFFFF;
1112           size_t ret;
1113 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
1114           /* @todo: adjust ssl_added to real value related to negociated cipher */
1115           size_t max_frag_len = mbedtls_ssl_get_max_frag_len(&state->ssl_context);
1116           max_len = LWIP_MIN(max_frag_len, max_len);
1117 #endif
1118           /* Adjust sndbuf of inner_conn with what added by SSL */
1119           ret = LWIP_MIN(sndbuf - ssl_added, max_len);
1120           LWIP_ASSERT("sndbuf overflow", ret <= 0xFFFF);
1121           return (u16_t)ret;
1122         }
1123       }
1124     }
1125   }
1126   /* fallback: use sendbuf of the inner connection */
1127   return altcp_default_sndbuf(conn);
1128 }
1129 
1130 /** Write data to a TLS connection. Calls into mbedTLS, which in turn calls into
1131  * @ref altcp_mbedtls_bio_send() to send the encrypted data
1132  */
1133 static err_t
altcp_mbedtls_write(struct altcp_pcb * conn,const void * dataptr,u16_t len,u8_t apiflags)1134 altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
1135 {
1136   int ret;
1137   altcp_mbedtls_state_t *state;
1138 
1139   LWIP_UNUSED_ARG(apiflags);
1140 
1141   if (conn == NULL) {
1142     return ERR_VAL;
1143   }
1144 
1145   state = (altcp_mbedtls_state_t *)conn->state;
1146   if (state == NULL) {
1147     /* @todo: which error? */
1148     return ERR_CLSD;
1149   }
1150   if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
1151     /* @todo: which error? */
1152     return ERR_VAL;
1153   }
1154 
1155   /* HACK: if thre is something left to send, try to flush it and only
1156      allow sending more if this succeeded (this is a hack because neither
1157      returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */
1158   if (state->ssl_context.out_left) {
1159     mbedtls_ssl_flush_output(&state->ssl_context);
1160     if (state->ssl_context.out_left) {
1161       return ERR_MEM;
1162     }
1163   }
1164   ret = mbedtls_ssl_write(&state->ssl_context, (const unsigned char *)dataptr, len);
1165   /* try to send data... */
1166   altcp_output(conn->inner_conn);
1167   if (ret >= 0) {
1168     if (ret == len) {
1169       state->flags |= ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT;
1170       return ERR_OK;
1171     } else {
1172       /* @todo/@fixme: assumption: either everything sent or error */
1173       LWIP_ASSERT("ret <= 0", 0);
1174       return ERR_MEM;
1175     }
1176   } else {
1177     if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
1178       /* @todo: convert error to err_t */
1179       return ERR_MEM;
1180     }
1181     LWIP_ASSERT("unhandled error", 0);
1182     return ERR_VAL;
1183   }
1184 }
1185 
1186 /** Send callback function called from mbedtls (set via mbedtls_ssl_set_bio)
1187  * This function is either called during handshake or when sending application
1188  * data via @ref altcp_mbedtls_write (or altcp_write)
1189  */
1190 static int
altcp_mbedtls_bio_send(void * ctx,const unsigned char * dataptr,size_t size)1191 altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size)
1192 {
1193   struct altcp_pcb *conn = (struct altcp_pcb *) ctx;
1194   int written = 0;
1195   size_t size_left = size;
1196   u8_t apiflags = TCP_WRITE_FLAG_COPY;
1197 
1198   LWIP_ASSERT("conn != NULL", conn != NULL);
1199   if ((conn == NULL) || (conn->inner_conn == NULL)) {
1200     return MBEDTLS_ERR_NET_INVALID_CONTEXT;
1201   }
1202 
1203   while (size_left) {
1204     u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF);
1205     err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags);
1206     if (err == ERR_OK) {
1207       written += write_len;
1208       size_left -= write_len;
1209     } else if (err == ERR_MEM) {
1210       if (written) {
1211         return written;
1212       }
1213       return 0; /* MBEDTLS_ERR_SSL_WANT_WRITE; */
1214     } else {
1215       LWIP_ASSERT("tls_write, tcp_write: err != ERR MEM", 0);
1216       /* @todo: return MBEDTLS_ERR_NET_CONN_RESET or MBEDTLS_ERR_NET_SEND_FAILED */
1217       return MBEDTLS_ERR_NET_SEND_FAILED;
1218     }
1219   }
1220   return written;
1221 }
1222 
1223 static u16_t
altcp_mbedtls_mss(struct altcp_pcb * conn)1224 altcp_mbedtls_mss(struct altcp_pcb *conn)
1225 {
1226   if (conn == NULL) {
1227     return 0;
1228   }
1229   /* @todo: LWIP_MIN(mss, mbedtls_ssl_get_max_frag_len()) ? */
1230   return altcp_mss(conn->inner_conn);
1231 }
1232 
1233 static void
altcp_mbedtls_dealloc(struct altcp_pcb * conn)1234 altcp_mbedtls_dealloc(struct altcp_pcb *conn)
1235 {
1236   /* clean up and free tls state */
1237   if (conn) {
1238     altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
1239     if (state) {
1240       mbedtls_ssl_free(&state->ssl_context);
1241       state->flags = 0;
1242       if (state->rx) {
1243         /* free leftover (unhandled) rx pbufs */
1244         pbuf_free(state->rx);
1245         state->rx = NULL;
1246       }
1247       altcp_mbedtls_free(state->conf, state);
1248       conn->state = NULL;
1249     }
1250   }
1251 }
1252 
1253 const struct altcp_functions altcp_mbedtls_functions = {
1254   altcp_mbedtls_set_poll,
1255   altcp_mbedtls_recved,
1256   altcp_default_bind,
1257   altcp_mbedtls_connect,
1258   altcp_mbedtls_listen,
1259   altcp_mbedtls_abort,
1260   altcp_mbedtls_close,
1261   altcp_default_shutdown,
1262   altcp_mbedtls_write,
1263   altcp_default_output,
1264   altcp_mbedtls_mss,
1265   altcp_mbedtls_sndbuf,
1266   altcp_default_sndqueuelen,
1267   altcp_default_nagle_disable,
1268   altcp_default_nagle_enable,
1269   altcp_default_nagle_disabled,
1270   altcp_default_setprio,
1271   altcp_mbedtls_dealloc,
1272   altcp_default_get_tcp_addrinfo,
1273   altcp_default_get_ip,
1274   altcp_default_get_port
1275 #if LWIP_TCP_KEEPALIVE
1276   , altcp_default_keepalive_disable
1277   , altcp_default_keepalive_enable
1278 #endif
1279 #ifdef LWIP_DEBUG
1280   , altcp_default_dbg_get_tcp_state
1281 #endif
1282 };
1283 
1284 #endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
1285 #endif /* LWIP_ALTCP */
1286