Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
altcp_tls_mbedtls.c
00001 /** 00002 * @file 00003 * Application layered TCP/TLS connection API (to be used from TCPIP thread) 00004 * 00005 * This file provides a TLS layer using mbedTLS 00006 */ 00007 00008 /* 00009 * Copyright (c) 2017 Simon Goldschmidt 00010 * All rights reserved. 00011 * 00012 * Redistribution and use in source and binary forms, with or without modification, 00013 * are permitted provided that the following conditions are met: 00014 * 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. The name of the author may not be used to endorse or promote products 00021 * derived from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00024 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00025 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00026 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00027 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00028 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00031 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00032 * OF SUCH DAMAGE. 00033 * 00034 * This file is part of the lwIP TCP/IP stack. 00035 * 00036 * Author: Simon Goldschmidt <goldsimon@gmx.de> 00037 * 00038 * Watch out: 00039 * - 'sent' is always called with len==0 to the upper layer. This is because keeping 00040 * track of the ratio of application data and TLS overhead would be too much. 00041 * 00042 * Mandatory security-related configuration: 00043 * - define ALTCP_MBEDTLS_RNG_FN to mbedtls_entropy_func to use the standard mbedTLS 00044 * entropy and ensure to add at least one strong entropy source to your mbedtls port 00045 * (implement mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong 00046 * entropy) 00047 * - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing 00048 * GOOD custom entropy 00049 * 00050 * Missing things / @todo: 00051 * - some unhandled/untested things migh be caught by LWIP_ASSERTs... 00052 */ 00053 00054 #include "lwip/opt.h" 00055 00056 #if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ 00057 00058 #include "lwip/apps/altcp_tls_mbedtls_opts.h" 00059 00060 #if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS 00061 00062 #include "lwip/altcp.h" 00063 #include "lwip/altcp_tls.h" 00064 #include "lwip/priv/altcp_priv.h" 00065 00066 #include "altcp_tls_mbedtls_structs.h" 00067 #include "altcp_tls_mbedtls_mem.h" 00068 00069 /* @todo: which includes are really needed? */ 00070 #include "mbedtls/entropy.h" 00071 #include "mbedtls/ctr_drbg.h" 00072 #include "mbedtls/certs.h" 00073 #include "mbedtls/x509.h" 00074 #include "mbedtls/ssl.h" 00075 #include "mbedtls/net.h" 00076 #include "mbedtls/error.h" 00077 #include "mbedtls/debug.h" 00078 #include "mbedtls/platform.h" 00079 #include "mbedtls/memory_buffer_alloc.h" 00080 #include "mbedtls/ssl_cache.h" 00081 00082 #include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */ 00083 00084 #include <string.h> 00085 00086 #ifndef ALTCP_MBEDTLS_ENTROPY_PTR 00087 #define ALTCP_MBEDTLS_ENTROPY_PTR NULL 00088 #endif 00089 #ifndef ALTCP_MBEDTLS_ENTROPY_LEN 00090 #define ALTCP_MBEDTLS_ENTROPY_LEN 0 00091 #endif 00092 00093 /* Variable prototype, the actual declaration is at the end of this file 00094 since it contains pointers to static functions declared here */ 00095 extern const struct altcp_functions altcp_mbedtls_functions; 00096 00097 /** Our global mbedTLS configuration (server-specific, not connection-specific) */ 00098 struct altcp_tls_config { 00099 mbedtls_ssl_config conf; 00100 mbedtls_entropy_context entropy; 00101 mbedtls_ctr_drbg_context ctr_drbg; 00102 mbedtls_x509_crt *cert; 00103 mbedtls_pk_context *pkey; 00104 mbedtls_x509_crt *ca; 00105 #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS 00106 /** Inter-connection cache for fast connection startup */ 00107 struct mbedtls_ssl_cache_context cache; 00108 #endif 00109 }; 00110 00111 static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err); 00112 static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn); 00113 static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state); 00114 static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state); 00115 static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size); 00116 00117 00118 /* callback functions from inner/lower connection: */ 00119 00120 /** Accept callback from lower connection (i.e. TCP) 00121 * Allocate one of our structures, assign it to the new connection's 'state' and 00122 * call the new connection's 'accepted' callback. If that succeeds, we wait 00123 * to receive connection setup handshake bytes from the client. 00124 */ 00125 static err_t 00126 altcp_mbedtls_lower_accept(void *arg, struct altcp_pcb *accepted_conn, err_t err) 00127 { 00128 struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg; 00129 if (listen_conn && listen_conn->state && listen_conn->accept) { 00130 err_t setup_err; 00131 altcp_mbedtls_state_t *listen_state = (altcp_mbedtls_state_t *)listen_conn->state; 00132 /* create a new altcp_conn to pass to the next 'accept' callback */ 00133 struct altcp_pcb *new_conn = altcp_alloc(); 00134 if (new_conn == NULL) { 00135 return ERR_MEM; 00136 } 00137 setup_err = altcp_mbedtls_setup(listen_state->conf, new_conn, accepted_conn); 00138 if (setup_err != ERR_OK) { 00139 altcp_free(new_conn); 00140 return setup_err; 00141 } 00142 return listen_conn->accept(listen_conn->arg, new_conn, err); 00143 } 00144 return ERR_ARG; 00145 } 00146 00147 /** Connected callback from lower connection (i.e. TCP). 00148 * Not really implemented/tested yet... 00149 */ 00150 static err_t 00151 altcp_mbedtls_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err) 00152 { 00153 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00154 LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ 00155 if (conn && conn->state) { 00156 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); 00157 /* upper connected is called when handshake is done */ 00158 if (err != ERR_OK) { 00159 if (conn->connected) { 00160 return conn->connected(conn->arg, conn, err); 00161 } 00162 } 00163 return altcp_mbedtls_lower_recv_process(conn, (altcp_mbedtls_state_t *)conn->state); 00164 } 00165 return ERR_VAL; 00166 } 00167 00168 /* Call recved for possibly more than an u16_t */ 00169 static void 00170 altcp_mbedtls_lower_recved(struct altcp_pcb *inner_conn, int recvd_cnt) 00171 { 00172 while (recvd_cnt > 0) { 00173 u16_t recvd_part = (u16_t)LWIP_MIN(recvd_cnt, 0xFFFF); 00174 altcp_recved (inner_conn, recvd_part); 00175 recvd_cnt -= recvd_part; 00176 } 00177 } 00178 00179 /** Recv callback from lower connection (i.e. TCP) 00180 * This one mainly differs between connection setup/handshake (data is fed into mbedTLS only) 00181 * and application phase (data is decoded by mbedTLS and passed on to the application). 00182 */ 00183 static err_t 00184 altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err) 00185 { 00186 altcp_mbedtls_state_t *state; 00187 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00188 00189 LWIP_ASSERT("no err expected", err == ERR_OK); 00190 LWIP_UNUSED_ARG(err); 00191 00192 if (!conn) { 00193 /* no connection given as arg? should not happen, but prevent pbuf/conn leaks */ 00194 if (p != NULL) { 00195 pbuf_free(p); 00196 } 00197 altcp_close (inner_conn); 00198 return ERR_CLSD; 00199 } 00200 state = (altcp_mbedtls_state_t *)conn->state; 00201 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); 00202 if (!state) { 00203 /* already closed */ 00204 if (p != NULL) { 00205 pbuf_free(p); 00206 } 00207 altcp_close (inner_conn); 00208 return ERR_CLSD; 00209 } 00210 00211 /* handle NULL pbuf (inner connection closed) */ 00212 if (p == NULL) { 00213 /* remote host sent FIN, remember this (SSL state is destroyed 00214 when both sides are closed only!) */ 00215 if ((state->flags & (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) == 00216 (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) { 00217 /* need to notify upper layer (e.g. 'accept' called or 'connect' succeeded) */ 00218 if ((state->rx != NULL) || (state->rx_app != NULL)) { 00219 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED; 00220 /* this is a normal close (FIN) but we have unprocessed data, so delay the FIN */ 00221 altcp_mbedtls_handle_rx_appldata(conn, state); 00222 return ERR_OK; 00223 } 00224 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED; 00225 if (conn->recv) { 00226 return conn->recv(conn->arg, conn, NULL, ERR_OK); 00227 } 00228 } else { 00229 /* before connection setup is done: call 'err' */ 00230 if (conn->err) { 00231 conn->err(conn->arg, ERR_CLSD); 00232 } 00233 altcp_close (conn); 00234 } 00235 return ERR_OK; 00236 } 00237 00238 /* If we come here, the connection is in good state (handshake phase or application data phase). 00239 Queue up the pbuf for processing as handshake data or application data. */ 00240 if (state->rx == NULL) { 00241 state->rx = p; 00242 } else { 00243 LWIP_ASSERT("rx pbuf overflow", (int)p->tot_len + (int)p->len <= 0xFFFF); 00244 pbuf_cat(state->rx, p); 00245 } 00246 return altcp_mbedtls_lower_recv_process(conn, state); 00247 } 00248 00249 static err_t 00250 altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state) 00251 { 00252 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { 00253 /* handle connection setup (handshake not done) */ 00254 int ret = mbedtls_ssl_handshake(&state->ssl_context); 00255 /* try to send data... */ 00256 altcp_output (conn->inner_conn); 00257 if (state->bio_bytes_read) { 00258 /* acknowledge all bytes read */ 00259 altcp_mbedtls_lower_recved(conn->inner_conn, state->bio_bytes_read); 00260 state->bio_bytes_read = 0; 00261 } 00262 00263 if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 00264 /* handshake not done, wait for more recv calls */ 00265 LWIP_ASSERT("in this state, the rx chain should be empty", state->rx == NULL); 00266 return ERR_OK; 00267 } 00268 if (ret != 0) { 00269 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret)); 00270 /* handshake failed, connection has to be closed */ 00271 if (conn->err) { 00272 conn->err(conn->arg, ERR_CLSD); 00273 } 00274 00275 if (altcp_close (conn) != ERR_OK) { 00276 altcp_abort (conn); 00277 } 00278 return ERR_OK; 00279 } 00280 /* If we come here, handshake succeeded. */ 00281 LWIP_ASSERT("state", state->bio_bytes_read == 0); 00282 LWIP_ASSERT("state", state->bio_bytes_appl == 0); 00283 state->flags |= ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE; 00284 /* issue "connect" callback" to upper connection (this can only happen for active open) */ 00285 if (conn->connected) { 00286 err_t err; 00287 err = conn->connected(conn->arg, conn, ERR_OK); 00288 if (err != ERR_OK) { 00289 return err; 00290 } 00291 } 00292 if (state->rx == NULL) { 00293 return ERR_OK; 00294 } 00295 } 00296 /* handle application data */ 00297 return altcp_mbedtls_handle_rx_appldata(conn, state); 00298 } 00299 00300 /* Pass queued decoded rx data to application */ 00301 static err_t 00302 altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state) 00303 { 00304 err_t err; 00305 struct pbuf *buf; 00306 LWIP_ASSERT("conn != NULL", conn != NULL); 00307 LWIP_ASSERT("state != NULL", state != NULL); 00308 buf = state->rx_app; 00309 if (buf) { 00310 state->rx_app = NULL; 00311 if (conn->recv) { 00312 u16_t tot_len = buf->tot_len; 00313 /* this needs to be increased first because the 'recved' call may come nested */ 00314 state->rx_passed_unrecved += tot_len; 00315 state->flags |= ALTCP_MBEDTLS_FLAGS_UPPER_CALLED; 00316 err = conn->recv(conn->arg, conn, buf, ERR_OK); 00317 if (err != ERR_OK) { 00318 if (err == ERR_ABRT) { 00319 return ERR_ABRT; 00320 } 00321 /* not received, leave the pbuf(s) queued (and decrease 'unrecved' again) */ 00322 LWIP_ASSERT("state == conn->state", state == conn->state); 00323 state->rx_app = buf; 00324 state->rx_passed_unrecved -= tot_len; 00325 LWIP_ASSERT("state->rx_passed_unrecved >= 0", state->rx_passed_unrecved >= 0); 00326 if (state->rx_passed_unrecved < 0) { 00327 state->rx_passed_unrecved = 0; 00328 } 00329 return err; 00330 } 00331 } else { 00332 pbuf_free(buf); 00333 } 00334 } else if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) == 00335 ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) { 00336 state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED; 00337 if (conn->recv) { 00338 return conn->recv(conn->arg, conn, NULL, ERR_OK); 00339 } 00340 } 00341 00342 /* application may have close the connection */ 00343 if (conn->state != state) { 00344 /* return error code to ensure altcp_mbedtls_handle_rx_appldata() exits the loop */ 00345 return ERR_CLSD; 00346 } 00347 return ERR_OK; 00348 } 00349 00350 /* Helper function that processes rx application data stored in rx pbuf chain */ 00351 static err_t 00352 altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state) 00353 { 00354 int ret; 00355 LWIP_ASSERT("state != NULL", state != NULL); 00356 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { 00357 /* handshake not done yet */ 00358 return ERR_VAL; 00359 } 00360 do { 00361 /* allocate a full-sized unchained PBUF_POOL: this is for RX! */ 00362 struct pbuf *buf = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL); 00363 if (buf == NULL) { 00364 /* We're short on pbufs, try again later from 'poll' or 'recv' callbacks. 00365 @todo: close on excessive allocation failures or leave this up to upper conn? */ 00366 return ERR_OK; 00367 } 00368 00369 /* decrypt application data, this pulls encrypted RX data off state->rx pbuf chain */ 00370 ret = mbedtls_ssl_read(&state->ssl_context, (unsigned char *)buf->payload, PBUF_POOL_BUFSIZE); 00371 if (ret < 0) { 00372 if (ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) { 00373 /* client is initiating a new connection using the same source port -> close connection or make handshake */ 00374 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("new connection on same source port\n")); 00375 LWIP_ASSERT("TODO: new connection on same source port, close this connection", 0); 00376 } else if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { 00377 if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { 00378 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was closed gracefully\n")); 00379 } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) { 00380 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was reset by peer\n")); 00381 } 00382 pbuf_free(buf); 00383 return ERR_OK; 00384 } else { 00385 pbuf_free(buf); 00386 return ERR_OK; 00387 } 00388 pbuf_free(buf); 00389 altcp_abort (conn); 00390 return ERR_ABRT; 00391 } else { 00392 err_t err; 00393 if (ret) { 00394 LWIP_ASSERT("bogus receive length", ret <= PBUF_POOL_BUFSIZE); 00395 /* trim pool pbuf to actually decoded length */ 00396 pbuf_realloc(buf, (u16_t)ret); 00397 00398 state->bio_bytes_appl += ret; 00399 if (mbedtls_ssl_get_bytes_avail(&state->ssl_context) == 0) { 00400 /* Record is done, now we know the share between application and protocol bytes 00401 and can adjust the RX window by the protocol bytes. 00402 The rest is 'recved' by the application calling our 'recved' fn. */ 00403 int overhead_bytes; 00404 LWIP_ASSERT("bogus byte counts", state->bio_bytes_read > state->bio_bytes_appl); 00405 overhead_bytes = state->bio_bytes_read - state->bio_bytes_appl; 00406 altcp_mbedtls_lower_recved(conn->inner_conn, overhead_bytes); 00407 state->bio_bytes_read = 0; 00408 state->bio_bytes_appl = 0; 00409 } 00410 00411 if (state->rx_app == NULL) { 00412 state->rx_app = buf; 00413 } else { 00414 pbuf_cat(state->rx_app, buf); 00415 } 00416 } else { 00417 pbuf_free(buf); 00418 buf = NULL; 00419 } 00420 err = altcp_mbedtls_pass_rx_data(conn, state); 00421 if (err != ERR_OK) { 00422 if (err == ERR_ABRT) { 00423 /* recv callback needs to return this as the pcb is deallocated */ 00424 return ERR_ABRT; 00425 } 00426 /* we hide all other errors as we retry feeding the pbuf to the app later */ 00427 return ERR_OK; 00428 } 00429 } 00430 } while (ret > 0); 00431 return ERR_OK; 00432 } 00433 00434 /** Receive callback function called from mbedtls (set via mbedtls_ssl_set_bio) 00435 * This function mainly copies data from pbufs and frees the pbufs after copying. 00436 */ 00437 static int 00438 altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len) 00439 { 00440 struct altcp_pcb *conn = (struct altcp_pcb *)ctx; 00441 altcp_mbedtls_state_t *state; 00442 struct pbuf *p; 00443 u16_t ret; 00444 u16_t copy_len; 00445 err_t err; 00446 00447 LWIP_UNUSED_ARG(err); /* for LWIP_NOASSERT */ 00448 if ((conn == NULL) || (conn->state == NULL)) { 00449 return MBEDTLS_ERR_NET_INVALID_CONTEXT; 00450 } 00451 state = (altcp_mbedtls_state_t *)conn->state; 00452 p = state->rx; 00453 00454 /* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */ 00455 00456 if ((p == NULL) || ((p->len == 0) && (p->next == NULL))) { 00457 if (p) { 00458 pbuf_free(p); 00459 } 00460 state->rx = NULL; 00461 if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) == 00462 ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) { 00463 /* close queued but not passed up yet */ 00464 return 0; 00465 } 00466 return MBEDTLS_ERR_SSL_WANT_READ; 00467 } 00468 /* limit number of bytes again to copy from first pbuf in a chain only */ 00469 copy_len = (u16_t)LWIP_MIN(len, p->len); 00470 /* copy the data */ 00471 ret = pbuf_copy_partial(p, buf, copy_len, 0); 00472 LWIP_ASSERT("ret == copy_len", ret == copy_len); 00473 /* hide the copied bytes from the pbuf */ 00474 err = pbuf_remove_header(p, ret); 00475 LWIP_ASSERT("error", err == ERR_OK); 00476 if (p->len == 0) { 00477 /* the first pbuf has been fully read, free it */ 00478 state->rx = p->next; 00479 p->next = NULL; 00480 pbuf_free(p); 00481 } 00482 00483 state->bio_bytes_read += (int)ret; 00484 return ret; 00485 } 00486 00487 /** Sent callback from lower connection (i.e. TCP) 00488 * This only informs the upper layer to try to send more, not about 00489 * the number of ACKed bytes. 00490 */ 00491 static err_t 00492 altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len) 00493 { 00494 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00495 LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ 00496 LWIP_UNUSED_ARG(len); 00497 if (conn) { 00498 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; 00499 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); 00500 if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { 00501 /* @todo: do something here? */ 00502 return ERR_OK; 00503 } 00504 /* try to send more if we failed before */ 00505 mbedtls_ssl_flush_output(&state->ssl_context); 00506 /* call upper sent with len==0 if the application already sent data */ 00507 if ((state->flags & ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT) && conn->sent) { 00508 return conn->sent(conn->arg, conn, 0); 00509 } 00510 } 00511 return ERR_OK; 00512 } 00513 00514 /** Poll callback from lower connection (i.e. TCP) 00515 * Just pass this on to the application. 00516 * @todo: retry sending? 00517 */ 00518 static err_t 00519 altcp_mbedtls_lower_poll(void *arg, struct altcp_pcb *inner_conn) 00520 { 00521 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00522 LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ 00523 if (conn) { 00524 LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); 00525 /* check if there's unreceived rx data */ 00526 if (conn->state) { 00527 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; 00528 /* try to send more if we failed before */ 00529 mbedtls_ssl_flush_output(&state->ssl_context); 00530 if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) { 00531 return ERR_ABRT; 00532 } 00533 } 00534 if (conn->poll) { 00535 return conn->poll(conn->arg, conn); 00536 } 00537 } 00538 return ERR_OK; 00539 } 00540 00541 static void 00542 altcp_mbedtls_lower_err(void *arg, err_t err) 00543 { 00544 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00545 if (conn) { 00546 conn->inner_conn = NULL; /* already freed */ 00547 if (conn->err) { 00548 conn->err(conn->arg, err); 00549 } 00550 altcp_free(conn); 00551 } 00552 } 00553 00554 /* setup functions */ 00555 00556 static void 00557 altcp_mbedtls_remove_callbacks(struct altcp_pcb *inner_conn) 00558 { 00559 altcp_arg (inner_conn, NULL); 00560 altcp_recv (inner_conn, NULL); 00561 altcp_sent (inner_conn, NULL); 00562 altcp_err (inner_conn, NULL); 00563 altcp_poll (inner_conn, NULL, inner_conn->pollinterval); 00564 } 00565 00566 static void 00567 altcp_mbedtls_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn) 00568 { 00569 altcp_arg (inner_conn, conn); 00570 altcp_recv (inner_conn, altcp_mbedtls_lower_recv); 00571 altcp_sent (inner_conn, altcp_mbedtls_lower_sent); 00572 altcp_err (inner_conn, altcp_mbedtls_lower_err); 00573 /* tcp_poll is set when interval is set by application */ 00574 /* listen is set totally different :-) */ 00575 } 00576 00577 static err_t 00578 altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn) 00579 { 00580 int ret; 00581 struct altcp_tls_config *config = (struct altcp_tls_config *)conf; 00582 altcp_mbedtls_state_t *state; 00583 if (!conf) { 00584 return ERR_ARG; 00585 } 00586 LWIP_ASSERT("invalid inner_conn", conn != inner_conn); 00587 00588 /* allocate mbedtls context */ 00589 state = altcp_mbedtls_alloc(conf); 00590 if (state == NULL) { 00591 return ERR_MEM; 00592 } 00593 /* initialize mbedtls context: */ 00594 mbedtls_ssl_init(&state->ssl_context); 00595 ret = mbedtls_ssl_setup(&state->ssl_context, &config->conf); 00596 if (ret != 0) { 00597 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_setup failed\n")); 00598 /* @todo: convert 'ret' to err_t */ 00599 altcp_mbedtls_free(conf, state); 00600 return ERR_MEM; 00601 } 00602 /* tell mbedtls about our I/O functions */ 00603 mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL); 00604 00605 altcp_mbedtls_setup_callbacks(conn, inner_conn); 00606 conn->inner_conn = inner_conn; 00607 conn->fns = &altcp_mbedtls_functions; 00608 conn->state = state; 00609 return ERR_OK; 00610 } 00611 00612 struct altcp_pcb * 00613 altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb) 00614 { 00615 struct altcp_pcb *ret; 00616 if (inner_pcb == NULL) { 00617 return NULL; 00618 } 00619 ret = altcp_alloc(); 00620 if (ret != NULL) { 00621 if (altcp_mbedtls_setup(config, ret, inner_pcb) != ERR_OK) { 00622 altcp_free(ret); 00623 return NULL; 00624 } 00625 } 00626 return ret; 00627 } 00628 00629 void * 00630 altcp_tls_context(struct altcp_pcb *conn) 00631 { 00632 if (conn && conn->state) { 00633 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; 00634 return &state->ssl_context; 00635 } 00636 return NULL; 00637 } 00638 00639 #if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF 00640 static void 00641 altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) 00642 { 00643 LWIP_UNUSED_ARG(ctx); 00644 LWIP_UNUSED_ARG(level); 00645 LWIP_UNUSED_ARG(file); 00646 LWIP_UNUSED_ARG(line); 00647 LWIP_UNUSED_ARG(str); 00648 00649 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("%s:%04d: %s", file, line, str)); 00650 } 00651 #endif 00652 00653 #ifndef ALTCP_MBEDTLS_RNG_FN 00654 /** ATTENTION: It is *really* important to *NOT* use this dummy RNG in production code!!!! */ 00655 static int 00656 dummy_rng(void *ctx, unsigned char *buffer, size_t len) 00657 { 00658 static size_t ctr; 00659 size_t i; 00660 LWIP_UNUSED_ARG(ctx); 00661 for (i = 0; i < len; i++) { 00662 buffer[i] = (unsigned char)++ctr; 00663 } 00664 return 0; 00665 } 00666 #define ALTCP_MBEDTLS_RNG_FN dummy_rng 00667 #endif /* ALTCP_MBEDTLS_RNG_FN */ 00668 00669 /** Create new TLS configuration 00670 * ATTENTION: Server certificate and private key have to be added outside this function! 00671 */ 00672 static struct altcp_tls_config * 00673 altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca) 00674 { 00675 size_t sz; 00676 int ret; 00677 struct altcp_tls_config *conf; 00678 mbedtls_x509_crt *mem; 00679 00680 if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) { 00681 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS, 00682 ("altcp_tls: TCP_WND is smaller than the RX decryption buffer, connection RX might stall!\n")); 00683 } 00684 00685 altcp_mbedtls_mem_init(); 00686 00687 sz = sizeof(struct altcp_tls_config); 00688 if (have_cert) { 00689 sz += sizeof(mbedtls_x509_crt); 00690 } 00691 if (have_ca) { 00692 sz += sizeof(mbedtls_x509_crt); 00693 } 00694 if (have_pkey) { 00695 sz += sizeof(mbedtls_pk_context); 00696 } 00697 00698 conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz); 00699 if (conf == NULL) { 00700 return NULL; 00701 } 00702 mem = (mbedtls_x509_crt *)(conf + 1); 00703 if (have_cert) { 00704 conf->cert = mem; 00705 mem++; 00706 } 00707 if (have_ca) { 00708 conf->ca = mem; 00709 mem++; 00710 } 00711 if (have_pkey) { 00712 conf->pkey = (mbedtls_pk_context *)mem; 00713 } 00714 00715 mbedtls_ssl_config_init(&conf->conf); 00716 mbedtls_entropy_init(&conf->entropy); 00717 mbedtls_ctr_drbg_init(&conf->ctr_drbg); 00718 00719 /* Seed the RNG */ 00720 ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN); 00721 if (ret != 0) { 00722 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret)); 00723 altcp_mbedtls_free_config(conf); 00724 return NULL; 00725 } 00726 00727 /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */ 00728 ret = mbedtls_ssl_config_defaults(&conf->conf, is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, 00729 MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); 00730 if (ret != 0) { 00731 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret)); 00732 altcp_mbedtls_free_config(conf); 00733 return NULL; 00734 } 00735 mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); 00736 00737 mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg); 00738 #if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF 00739 mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout); 00740 #endif 00741 #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS 00742 mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); 00743 mbedtls_ssl_cache_set_timeout(&conf->cache, 30); 00744 mbedtls_ssl_cache_set_max_entries(&conf->cache, 30); 00745 #endif 00746 00747 return conf; 00748 } 00749 00750 /** Create new TLS configuration 00751 * This is a suboptimal version that gets the encrypted private key and its password, 00752 * as well as the server certificate. 00753 */ 00754 struct altcp_tls_config * 00755 altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len, 00756 const u8_t *privkey_pass, size_t privkey_pass_len, 00757 const u8_t *cert, size_t cert_len) 00758 { 00759 int ret; 00760 mbedtls_x509_crt *srvcert; 00761 mbedtls_pk_context *pkey; 00762 struct altcp_tls_config *conf = altcp_tls_create_config(1, 1, 1, 0); 00763 if (conf == NULL) { 00764 return NULL; 00765 } 00766 00767 srvcert = conf->cert; 00768 mbedtls_x509_crt_init(srvcert); 00769 00770 pkey = conf->pkey; 00771 mbedtls_pk_init(pkey); 00772 00773 /* Load the certificates and private key */ 00774 ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len); 00775 if (ret != 0) { 00776 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret)); 00777 altcp_mbedtls_free_config(conf); 00778 return NULL; 00779 } 00780 00781 ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len); 00782 if (ret != 0) { 00783 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret)); 00784 mbedtls_x509_crt_free(srvcert); 00785 altcp_mbedtls_free_config(conf); 00786 return NULL; 00787 } 00788 00789 mbedtls_ssl_conf_ca_chain(&conf->conf, srvcert->next, NULL); 00790 ret = mbedtls_ssl_conf_own_cert(&conf->conf, srvcert, pkey); 00791 if (ret != 0) { 00792 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret)); 00793 mbedtls_x509_crt_free(srvcert); 00794 mbedtls_pk_free(pkey); 00795 altcp_mbedtls_free_config(conf); 00796 return NULL; 00797 } 00798 return conf; 00799 } 00800 00801 static struct altcp_tls_config * 00802 altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth) 00803 { 00804 int ret; 00805 struct altcp_tls_config *conf = altcp_tls_create_config(0, is_2wayauth, is_2wayauth, ca != NULL); 00806 if (conf == NULL) { 00807 return NULL; 00808 } 00809 00810 /* Initialize the CA certificate if provided 00811 * CA certificate is optional (to save memory) but recommended for production environment 00812 * Without CA certificate, connection will be prone to man-in-the-middle attacks */ 00813 if (ca) { 00814 mbedtls_x509_crt_init(conf->ca); 00815 ret = mbedtls_x509_crt_parse(conf->ca, ca, ca_len); 00816 if (ret != 0) { 00817 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse ca failed: %d 0x%x", ret, -1*ret)); 00818 altcp_mbedtls_free_config(conf); 00819 return NULL; 00820 } 00821 00822 mbedtls_ssl_conf_ca_chain(&conf->conf, conf->ca, NULL); 00823 } 00824 return conf; 00825 } 00826 00827 struct altcp_tls_config * 00828 altcp_tls_create_config_client(const u8_t *ca, size_t ca_len) 00829 { 00830 return altcp_tls_create_config_client_common(ca, ca_len, 0); 00831 } 00832 00833 struct altcp_tls_config * 00834 altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len, 00835 const u8_t *privkey_pass, size_t privkey_pass_len, 00836 const u8_t *cert, size_t cert_len) 00837 { 00838 int ret; 00839 struct altcp_tls_config *conf; 00840 00841 if (!cert || !privkey) { 00842 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("altcp_tls_create_config_client_2wayauth: certificate and priv key required")); 00843 return NULL; 00844 } 00845 00846 conf = altcp_tls_create_config_client_common(ca, ca_len, 1); 00847 if (conf == NULL) { 00848 return NULL; 00849 } 00850 00851 /* Initialize the client certificate and corresponding private key */ 00852 mbedtls_x509_crt_init(conf->cert); 00853 ret = mbedtls_x509_crt_parse(conf->cert, cert, cert_len); 00854 if (ret != 0) { 00855 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse cert failed: %d 0x%x", ret, -1*ret)); 00856 altcp_mbedtls_free_config(conf->cert); 00857 return NULL; 00858 } 00859 00860 mbedtls_pk_init(conf->pkey); 00861 ret = mbedtls_pk_parse_key(conf->pkey, privkey, privkey_len, privkey_pass, privkey_pass_len); 00862 if (ret != 0) { 00863 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_key failed: %d 0x%x", ret, -1*ret)); 00864 altcp_mbedtls_free_config(conf); 00865 return NULL; 00866 } 00867 00868 ret = mbedtls_ssl_conf_own_cert(&conf->conf, conf->cert, conf->pkey); 00869 if (ret != 0) { 00870 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d 0x%x", ret, -1*ret)); 00871 altcp_mbedtls_free_config(conf); 00872 return NULL; 00873 } 00874 00875 return conf; 00876 } 00877 00878 void 00879 altcp_tls_free_config(struct altcp_tls_config *conf) 00880 { 00881 if (conf->pkey) { 00882 mbedtls_pk_free(conf->pkey); 00883 } 00884 if (conf->cert) { 00885 mbedtls_x509_crt_free(conf->cert); 00886 } 00887 if (conf->ca) { 00888 mbedtls_x509_crt_free(conf->ca); 00889 } 00890 altcp_mbedtls_free_config(conf); 00891 } 00892 00893 /* "virtual" functions */ 00894 static void 00895 altcp_mbedtls_set_poll(struct altcp_pcb *conn, u8_t interval) 00896 { 00897 if (conn != NULL) { 00898 altcp_poll (conn->inner_conn, altcp_mbedtls_lower_poll, interval); 00899 } 00900 } 00901 00902 static void 00903 altcp_mbedtls_recved(struct altcp_pcb *conn, u16_t len) 00904 { 00905 u16_t lower_recved; 00906 altcp_mbedtls_state_t *state; 00907 if (conn == NULL) { 00908 return; 00909 } 00910 state = (altcp_mbedtls_state_t *)conn->state; 00911 if (state == NULL) { 00912 return; 00913 } 00914 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { 00915 return; 00916 } 00917 lower_recved = len; 00918 if (lower_recved > state->rx_passed_unrecved) { 00919 LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("bogus recved count (len > state->rx_passed_unrecved / %d / %d)", 00920 len, state->rx_passed_unrecved)); 00921 lower_recved = (u16_t)state->rx_passed_unrecved; 00922 } 00923 state->rx_passed_unrecved -= lower_recved; 00924 00925 altcp_recved (conn->inner_conn, lower_recved); 00926 } 00927 00928 static err_t 00929 altcp_mbedtls_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected) 00930 { 00931 if (conn == NULL) { 00932 return ERR_VAL; 00933 } 00934 conn->connected = connected; 00935 return altcp_connect (conn->inner_conn, ipaddr, port, altcp_mbedtls_lower_connected); 00936 } 00937 00938 static struct altcp_pcb * 00939 altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err) 00940 { 00941 struct altcp_pcb *lpcb; 00942 if (conn == NULL) { 00943 return NULL; 00944 } 00945 lpcb = altcp_listen_with_backlog_and_err (conn->inner_conn, backlog, err); 00946 if (lpcb != NULL) { 00947 conn->inner_conn = lpcb; 00948 altcp_accept (lpcb, altcp_mbedtls_lower_accept); 00949 return conn; 00950 } 00951 return NULL; 00952 } 00953 00954 static void 00955 altcp_mbedtls_abort(struct altcp_pcb *conn) 00956 { 00957 if (conn != NULL) { 00958 altcp_abort (conn->inner_conn); 00959 } 00960 } 00961 00962 static err_t 00963 altcp_mbedtls_close(struct altcp_pcb *conn) 00964 { 00965 struct altcp_pcb *inner_conn; 00966 if (conn == NULL) { 00967 return ERR_VAL; 00968 } 00969 inner_conn = conn->inner_conn; 00970 if (inner_conn) { 00971 err_t err; 00972 altcp_poll_fn oldpoll = inner_conn->poll; 00973 altcp_mbedtls_remove_callbacks(conn->inner_conn); 00974 err = altcp_close (conn->inner_conn); 00975 if (err != ERR_OK) { 00976 /* not closed, set up all callbacks again */ 00977 altcp_mbedtls_setup_callbacks(conn, inner_conn); 00978 /* poll callback is not included in the above */ 00979 altcp_poll (inner_conn, oldpoll, inner_conn->pollinterval); 00980 return err; 00981 } 00982 conn->inner_conn = NULL; 00983 } 00984 altcp_free(conn); 00985 return ERR_OK; 00986 } 00987 00988 /** Allow caller of altcp_write() to limit to negotiated chunk size 00989 * or remaining sndbuf space of inner_conn. 00990 */ 00991 static u16_t 00992 altcp_mbedtls_sndbuf(struct altcp_pcb *conn) 00993 { 00994 if (conn) { 00995 altcp_mbedtls_state_t *state; 00996 state = (altcp_mbedtls_state_t*)conn->state; 00997 if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { 00998 return 0; 00999 } 01000 if (conn->inner_conn) { 01001 u16_t sndbuf = altcp_sndbuf (conn->inner_conn); 01002 /* Take care of record header, IV, AuthTag */ 01003 int ssl_expan = mbedtls_ssl_get_record_expansion(&state->ssl_context); 01004 if (ssl_expan > 0) { 01005 size_t ssl_added = (u16_t)LWIP_MIN(ssl_expan, 0xFFFF); 01006 /* internal sndbuf smaller than our offset */ 01007 if (ssl_added < sndbuf) { 01008 size_t max_len = 0xFFFF; 01009 size_t ret; 01010 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) 01011 /* @todo: adjust ssl_added to real value related to negociated cipher */ 01012 size_t max_frag_len = mbedtls_ssl_get_max_frag_len(&state->ssl_context); 01013 max_len = LWIP_MIN(max_frag_len, max_len); 01014 #endif 01015 /* Adjust sndbuf of inner_conn with what added by SSL */ 01016 ret = LWIP_MIN(sndbuf - ssl_added, max_len); 01017 LWIP_ASSERT("sndbuf overflow", ret <= 0xFFFF); 01018 return (u16_t)ret; 01019 } 01020 } 01021 } 01022 } 01023 /* fallback: use sendbuf of the inner connection */ 01024 return altcp_default_sndbuf(conn); 01025 } 01026 01027 /** Write data to a TLS connection. Calls into mbedTLS, which in turn calls into 01028 * @ref altcp_mbedtls_bio_send() to send the encrypted data 01029 */ 01030 static err_t 01031 altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags) 01032 { 01033 int ret; 01034 altcp_mbedtls_state_t *state; 01035 01036 LWIP_UNUSED_ARG(apiflags); 01037 01038 if (conn == NULL) { 01039 return ERR_VAL; 01040 } 01041 01042 state = (altcp_mbedtls_state_t *)conn->state; 01043 if (state == NULL) { 01044 /* @todo: which error? */ 01045 return ERR_CLSD; 01046 } 01047 if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { 01048 /* @todo: which error? */ 01049 return ERR_VAL; 01050 } 01051 01052 /* HACK: if thre is something left to send, try to flush it and only 01053 allow sending more if this succeeded (this is a hack because neither 01054 returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */ 01055 if (state->ssl_context.out_left) { 01056 mbedtls_ssl_flush_output(&state->ssl_context); 01057 if (state->ssl_context.out_left) { 01058 return ERR_MEM; 01059 } 01060 } 01061 ret = mbedtls_ssl_write(&state->ssl_context, (const unsigned char *)dataptr, len); 01062 /* try to send data... */ 01063 altcp_output (conn->inner_conn); 01064 if (ret >= 0) { 01065 if (ret == len) { 01066 state->flags |= ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT; 01067 return ERR_OK; 01068 } else { 01069 /* @todo/@fixme: assumption: either everything sent or error */ 01070 LWIP_ASSERT("ret <= 0", 0); 01071 return ERR_MEM; 01072 } 01073 } else { 01074 if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 01075 /* @todo: convert error to err_t */ 01076 return ERR_MEM; 01077 } 01078 LWIP_ASSERT("unhandled error", 0); 01079 return ERR_VAL; 01080 } 01081 } 01082 01083 /** Send callback function called from mbedtls (set via mbedtls_ssl_set_bio) 01084 * This function is either called during handshake or when sending application 01085 * data via @ref altcp_mbedtls_write (or altcp_write) 01086 */ 01087 static int 01088 altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size) 01089 { 01090 struct altcp_pcb *conn = (struct altcp_pcb *) ctx; 01091 int written = 0; 01092 size_t size_left = size; 01093 u8_t apiflags = TCP_WRITE_FLAG_COPY; 01094 01095 LWIP_ASSERT("conn != NULL", conn != NULL); 01096 if ((conn == NULL) || (conn->inner_conn == NULL)) { 01097 return MBEDTLS_ERR_NET_INVALID_CONTEXT; 01098 } 01099 01100 while (size_left) { 01101 u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF); 01102 err_t err = altcp_write (conn->inner_conn, (const void *)dataptr, write_len, apiflags); 01103 if (err == ERR_OK) { 01104 written += write_len; 01105 size_left -= write_len; 01106 } else if (err == ERR_MEM) { 01107 if (written) { 01108 return written; 01109 } 01110 return 0; /* MBEDTLS_ERR_SSL_WANT_WRITE; */ 01111 } else { 01112 LWIP_ASSERT("tls_write, tcp_write: err != ERR MEM", 0); 01113 /* @todo: return MBEDTLS_ERR_NET_CONN_RESET or MBEDTLS_ERR_NET_SEND_FAILED */ 01114 return MBEDTLS_ERR_NET_SEND_FAILED; 01115 } 01116 } 01117 return written; 01118 } 01119 01120 static u16_t 01121 altcp_mbedtls_mss(struct altcp_pcb *conn) 01122 { 01123 if (conn == NULL) { 01124 return 0; 01125 } 01126 /* @todo: LWIP_MIN(mss, mbedtls_ssl_get_max_frag_len()) ? */ 01127 return altcp_mss (conn->inner_conn); 01128 } 01129 01130 static void 01131 altcp_mbedtls_dealloc(struct altcp_pcb *conn) 01132 { 01133 /* clean up and free tls state */ 01134 if (conn) { 01135 altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; 01136 if (state) { 01137 mbedtls_ssl_free(&state->ssl_context); 01138 state->flags = 0; 01139 if (state->rx) { 01140 /* free leftover (unhandled) rx pbufs */ 01141 pbuf_free(state->rx); 01142 state->rx = NULL; 01143 } 01144 altcp_mbedtls_free(state->conf, state); 01145 conn->state = NULL; 01146 } 01147 } 01148 } 01149 01150 const struct altcp_functions altcp_mbedtls_functions = { 01151 altcp_mbedtls_set_poll, 01152 altcp_mbedtls_recved, 01153 altcp_default_bind, 01154 altcp_mbedtls_connect, 01155 altcp_mbedtls_listen, 01156 altcp_mbedtls_abort, 01157 altcp_mbedtls_close, 01158 altcp_default_shutdown, 01159 altcp_mbedtls_write, 01160 altcp_default_output, 01161 altcp_mbedtls_mss, 01162 altcp_mbedtls_sndbuf, 01163 altcp_default_sndqueuelen, 01164 altcp_default_nagle_disable, 01165 altcp_default_nagle_enable, 01166 altcp_default_nagle_disabled, 01167 altcp_default_setprio, 01168 altcp_mbedtls_dealloc, 01169 altcp_default_get_tcp_addrinfo, 01170 altcp_default_get_ip, 01171 altcp_default_get_port 01172 #ifdef LWIP_DEBUG 01173 , altcp_default_dbg_get_tcp_state 01174 #endif 01175 }; 01176 01177 #endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */ 01178 #endif /* LWIP_ALTCP */
Generated on Tue Jul 12 2022 13:54:01 by
1.7.2