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