diff --git a/src/apps/altcp_tls/altcp_tls_mbedtls.c b/src/apps/altcp_tls/altcp_tls_mbedtls.c index 770e1dde..35b18155 100644 --- a/src/apps/altcp_tls/altcp_tls_mbedtls.c +++ b/src/apps/altcp_tls/altcp_tls_mbedtls.c @@ -96,8 +96,6 @@ extern const struct altcp_functions altcp_mbedtls_functions; /** Our global mbedTLS configuration (server-specific, not connection-specific) */ struct altcp_tls_config { mbedtls_ssl_config conf; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; mbedtls_x509_crt *cert; mbedtls_pk_context *pkey; u8_t cert_count; @@ -114,6 +112,14 @@ struct altcp_tls_config { #endif }; +/** Entropy and random generator are shared by all mbedTLS configuration */ +struct altcp_tls_entropy_rng { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + int ref; +}; +static struct altcp_tls_entropy_rng *altcp_tls_entropy_rng; + static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err); static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn); static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state); @@ -706,15 +712,32 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav } mbedtls_ssl_config_init(&conf->conf); - mbedtls_entropy_init(&conf->entropy); - mbedtls_ctr_drbg_init(&conf->ctr_drbg); - /* Seed the RNG */ - ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, mbedtls_entropy_func, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret)); - altcp_mbedtls_free_config(conf); - return NULL; + if (!altcp_tls_entropy_rng) { + altcp_tls_entropy_rng = (struct altcp_tls_entropy_rng *)altcp_mbedtls_alloc_config(sizeof(struct altcp_tls_entropy_rng)); + if (altcp_tls_entropy_rng) { + altcp_tls_entropy_rng->ref = 1; + mbedtls_entropy_init(&altcp_tls_entropy_rng->entropy); + mbedtls_ctr_drbg_init(&altcp_tls_entropy_rng->ctr_drbg); + /* Seed the RNG, only once */ + ret = mbedtls_ctr_drbg_seed(&altcp_tls_entropy_rng->ctr_drbg, + mbedtls_entropy_func, &altcp_tls_entropy_rng->entropy, + ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN); + if (ret != 0) { + LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret)); + mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg); + mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy); + altcp_mbedtls_free_config(altcp_tls_entropy_rng); + altcp_tls_entropy_rng = NULL; + altcp_mbedtls_free_config(conf); + return NULL; + } + } else { + altcp_mbedtls_free_config(conf); + return NULL; + } + } else { + altcp_tls_entropy_rng->ref++; } /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */ @@ -722,12 +745,18 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret)); + if (altcp_tls_entropy_rng->ref == 1) { + mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg); + mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy); + altcp_mbedtls_free_config(altcp_tls_entropy_rng); + altcp_tls_entropy_rng = NULL; + } altcp_mbedtls_free_config(conf); return NULL; } mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg); + mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg); #if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout); #endif @@ -740,7 +769,7 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav #if defined(MBEDTLS_SSL_SESSION_TICKETS) && ALTCP_MBEDTLS_USE_SESSION_TICKETS mbedtls_ssl_ticket_init(&conf->ticket_ctx); - ret = mbedtls_ssl_ticket_setup(&conf->ticket_ctx, mbedtls_ctr_drbg_random, &conf->ctr_drbg, + ret = mbedtls_ssl_ticket_setup(&conf->ticket_ctx, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg, ALTCP_MBEDTLS_SESSION_TICKET_CIPHER, ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS); if (ret) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_ticket_setup failed: %d\n", ret)); @@ -752,7 +781,6 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav &conf->ticket_ctx); #endif - return conf; } @@ -929,6 +957,19 @@ altcp_tls_free_config(struct altcp_tls_config *conf) mbedtls_x509_crt_free(conf->ca); } altcp_mbedtls_free_config(conf); + if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref) + altcp_tls_entropy_rng->ref--; +} + +void +altcp_tls_free_entropy(void) +{ + if (altcp_tls_entropy_rng && altcp_tls_entropy_rng->ref == 0) { + mbedtls_ctr_drbg_free(&altcp_tls_entropy_rng->ctr_drbg); + mbedtls_entropy_free(&altcp_tls_entropy_rng->entropy); + altcp_mbedtls_free_config(altcp_tls_entropy_rng); + altcp_tls_entropy_rng = NULL; + } } /* "virtual" functions */ diff --git a/src/include/lwip/altcp_tls.h b/src/include/lwip/altcp_tls.h index 94da12f6..cf09d490 100644 --- a/src/include/lwip/altcp_tls.h +++ b/src/include/lwip/altcp_tls.h @@ -99,6 +99,17 @@ struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca, */ void altcp_tls_free_config(struct altcp_tls_config *conf); +/** @ingroup altcp_tls + * Free an ALTCP_TLS global entropy instance. + * All ALTCP_TLS configuration are linked to one altcp_tls_entropy_rng structure + * that handle an unique system entropy & ctr_drbg instance. + * This function allow application to free this altcp_tls_entropy_rng structure + * when all configuration referencing it were destroyed. + * This function does nothing if some ALTCP_TLS configuration handle are still + * active. + */ +void altcp_tls_free_entropy(void); + /** @ingroup altcp_tls * Create new ALTCP_TLS layer wrapping an existing pcb as inner connection (e.g. TLS over TCP) */