source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/lwip-2.1.2/src/apps/altcp_tls/altcp_tls_mbedtls.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

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