From 89be04ce7a4feca4db0e6b8a4c18cda18b913bd9 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Sat, 24 Nov 2018 13:41:34 +0100 Subject: [PATCH] altcp_tls: add functions to create servers with multiple certificates (cherry picked from commit 3f583a17575f5180d767c9d9eaf5ef3a5aa21501) --- src/apps/altcp_tls/altcp_tls_mbedtls.c | 118 ++++++++++++++++--------- src/include/lwip/altcp_tls.h | 17 +++- 2 files changed, 94 insertions(+), 41 deletions(-) diff --git a/src/apps/altcp_tls/altcp_tls_mbedtls.c b/src/apps/altcp_tls/altcp_tls_mbedtls.c index ea9303ca..574fcb93 100644 --- a/src/apps/altcp_tls/altcp_tls_mbedtls.c +++ b/src/apps/altcp_tls/altcp_tls_mbedtls.c @@ -100,6 +100,10 @@ struct altcp_tls_config { mbedtls_ctr_drbg_context ctr_drbg; mbedtls_x509_crt *cert; mbedtls_pk_context *pkey; + uint8_t cert_count; + uint8_t cert_max; + uint8_t pkey_count; + uint8_t pkey_max; mbedtls_x509_crt *ca; #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE /** Inter-connection cache for fast connection startup */ @@ -657,7 +661,7 @@ altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char * ATTENTION: Server certificate and private key have to be added outside this function! */ static struct altcp_tls_config * -altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca) +altcp_tls_create_config(int is_server, uint8_t cert_count, uint8_t pkey_count, int have_ca) { size_t sz; int ret; @@ -672,30 +676,32 @@ altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca altcp_mbedtls_mem_init(); sz = sizeof(struct altcp_tls_config); - if (have_cert) { - sz += sizeof(mbedtls_x509_crt); + if (cert_count > 0) { + sz += (cert_count * sizeof(mbedtls_x509_crt)); } if (have_ca) { sz += sizeof(mbedtls_x509_crt); } - if (have_pkey) { - sz += sizeof(mbedtls_pk_context); + if (pkey_count > 0) { + sz += (pkey_count * sizeof(mbedtls_pk_context)); } conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz); if (conf == NULL) { return NULL; } + conf->cert_max = cert_count; mem = (mbedtls_x509_crt *)(conf + 1); - if (have_cert) { + if (cert_count > 0) { conf->cert = mem; - mem++; + mem += cert_count; } if (have_ca) { conf->ca = mem; mem++; } - if (have_pkey) { + conf->pkey_max = pkey_count; + if (pkey_count > 0) { conf->pkey = (mbedtls_pk_context *)mem; } @@ -750,6 +756,66 @@ altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca return conf; } +struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count) +{ + struct altcp_tls_config *conf = altcp_tls_create_config(1, cert_count, cert_count, 0); + if (conf == NULL) { + return NULL; + } + + mbedtls_ssl_conf_ca_chain(&conf->conf, NULL, NULL); + return conf; +} + +err_t 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) +{ + int ret; + mbedtls_x509_crt *srvcert; + mbedtls_pk_context *pkey; + + if (config->cert_count >= config->cert_max) { + return ERR_MEM; + } + if (config->pkey_count >= config->pkey_max) { + return ERR_MEM; + } + + srvcert = config->cert + config->cert_count; + mbedtls_x509_crt_init(srvcert); + + pkey = config->pkey + config->pkey_count; + mbedtls_pk_init(pkey); + + /* Load the certificates and private key */ + ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len); + if (ret != 0) { + LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret)); + return ERR_VAL; + } + + ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len); + if (ret != 0) { + LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret)); + mbedtls_x509_crt_free(srvcert); + return ERR_VAL; + } + + ret = mbedtls_ssl_conf_own_cert(&config->conf, srvcert, pkey); + if (ret != 0) { + LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret)); + mbedtls_x509_crt_free(srvcert); + mbedtls_pk_free(pkey); + return ERR_VAL; + } + + config->cert_count++; + config->pkey_count++; + return ERR_OK; +} + /** Create new TLS configuration * This is a suboptimal version that gets the encrypted private key and its password, * as well as the server certificate. @@ -759,45 +825,17 @@ altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_ const u8_t *privkey_pass, size_t privkey_pass_len, const u8_t *cert, size_t cert_len) { - int ret; - mbedtls_x509_crt *srvcert; - mbedtls_pk_context *pkey; - struct altcp_tls_config *conf = altcp_tls_create_config(1, 1, 1, 0); + struct altcp_tls_config *conf = altcp_tls_create_config_server(1); if (conf == NULL) { return NULL; } - srvcert = conf->cert; - mbedtls_x509_crt_init(srvcert); - - pkey = conf->pkey; - mbedtls_pk_init(pkey); - - /* Load the certificates and private key */ - ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret)); + if (altcp_tls_config_server_add_privkey_cert(conf, privkey, privkey_len, + privkey_pass, privkey_pass_len, cert, cert_len) != ERR_OK) { altcp_mbedtls_free_config(conf); return NULL; } - ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret)); - mbedtls_x509_crt_free(srvcert); - altcp_mbedtls_free_config(conf); - return NULL; - } - - mbedtls_ssl_conf_ca_chain(&conf->conf, srvcert->next, NULL); - ret = mbedtls_ssl_conf_own_cert(&conf->conf, srvcert, pkey); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret)); - mbedtls_x509_crt_free(srvcert); - mbedtls_pk_free(pkey); - altcp_mbedtls_free_config(conf); - return NULL; - } return conf; } @@ -805,7 +843,7 @@ static struct altcp_tls_config * altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth) { int ret; - struct altcp_tls_config *conf = altcp_tls_create_config(0, is_2wayauth, is_2wayauth, ca != NULL); + struct altcp_tls_config *conf = altcp_tls_create_config(0, (is_2wayauth) ? 1 : 0, (is_2wayauth) ? 1 : 0, ca != NULL); if (conf == NULL) { return NULL; } diff --git a/src/include/lwip/altcp_tls.h b/src/include/lwip/altcp_tls.h index 7b17c608..87b2761e 100644 --- a/src/include/lwip/altcp_tls.h +++ b/src/include/lwip/altcp_tls.h @@ -61,7 +61,22 @@ extern "C" { struct altcp_tls_config; /** @ingroup altcp_tls - * Create an ALTCP_TLS server configuration handle + * Create an ALTCP_TLS server configuration handle prepared for multiple certificates + */ +struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count); + +/** @ingroup altcp_tls + * Add a certificate to an ALTCP_TLS server configuration handle + */ +err_t 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); + +/** @ingroup altcp_tls + * Create an ALTCP_TLS server configuration handle with one certificate + * (short version of calling @ref altcp_tls_create_config_server and + * @ref altcp_tls_config_server_add_privkey_cert) */ 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,