Skip to content

Commit

Permalink
moved to use the CERTIFICATE SELECTION HOOK instead of the SNI HOOK, …
Browse files Browse the repository at this point in the history
…since it has access to more information, so the application can make a more informed decision on which certificate to serve (such as alpn value, server certificate type, etc.)
  • Loading branch information
axos88 committed Oct 10, 2022
1 parent 690617b commit 39a6ec0
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 69 deletions.
9 changes: 5 additions & 4 deletions components/esp-tls/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ menu "ESP-TLS"
help
Sets the session ticket timeout used in the tls server.

config ESP_TLS_SERVER_SNI_HOOK
bool "Server name identification hook"
config ESP_TLS_SERVER_CERT_SELECT_HOOK
bool "Certificate selection hook"
depends on ESP_TLS_USING_MBEDTLS
help
Ability to configure and use an SNI Callback during server handshake,
to select a certificate to present to the client for example.
Ability to configure and use a certificate selection callback during server handshake,
to select a certificate to present to the client based on the TLS extensions supplied in
the client hello (alpn, sni, etc).

config ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL
bool "ESP-TLS Server: Set minimum Certificate Verification mode to Optional"
Expand Down
23 changes: 14 additions & 9 deletions components/esp-tls/esp_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,19 @@ typedef struct esp_tls_server_session_ticket_ctx {
} esp_tls_server_session_ticket_ctx_t;
#endif


#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
/**
* @brief SNI callback function prototype
* @brief tls handshake callback
* Can be used to configure per-handshake attributes for the TLS connection.
* E.g. Client certificate / Key, Authmode, Client CA verification
* E.g. Client certificate / Key, Authmode, Client CA verification, etc.
*
* @param p_info Input data provided when registering the callback
* @param ssl mbedtls_ssl_context that can be used for changing settings
* @param name advertised server name by the client
* @param len length of the name buffer
* @return The reutn value of the callback must be 0 if successful,
* or a specific MBEDTLS_ERR_XXX code, which will cause the handhsake to abort
*/
typedef int esp_tls_server_sni_callback(void *p_info, mbedtls_ssl_context *ssl, const unsigned char *name, size_t name_len);
typedef mbedtls_ssl_hs_cb_t esp_tls_handshake_callback;
#endif

typedef struct esp_tls_cfg_server {
const char **alpn_protos; /*!< Application protocols required for HTTP2.
Expand Down Expand Up @@ -272,10 +274,13 @@ typedef struct esp_tls_cfg_server {
to free the data associated with this context. */
#endif

#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
esp_tls_server_sni_callback *sni_callback; /*!< Server Name Identification callback to use */
void *sni_callback_p_info; /*!< Data to pass to the SNI callback. */
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
esp_tls_handshake_callback cert_select_cb; /*!< Certificate selection callback that gets called after ClientHello is processed.
Can be used as an SNI callback, but also has access to other
TLS extensions, such as ALPN and server_certificate_type . */
#endif

void *userdata; /*!< User data to be add to the ssl context. Can be retrieved by callbacks */
} esp_tls_cfg_server_t;

/**
Expand Down
24 changes: 13 additions & 11 deletions components/esp-tls/esp_tls_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,12 +509,21 @@ esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls)
return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED;
}

mbedtls_ssl_conf_set_user_data_p(&tls->conf, cfg->userdata);

#ifdef CONFIG_MBEDTLS_SSL_ALPN
if (cfg->alpn_protos) {
mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos);
}
#endif

#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
if (cfg->cert_select_cb != NULL) {
ESP_LOGI(TAG, "Initializing server side certificate selection callback");
mbedtls_ssl_conf_cert_cb(&tls->conf, cfg->cert_select_cb);
}
#endif

if (cfg->cacert_buf != NULL) {
esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes);
if (esp_ret != ESP_OK) {
Expand Down Expand Up @@ -566,11 +575,11 @@ esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls)
return esp_ret;
}
} else {
#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
if (cfg->sni_callback == NULL) {
ESP_LOGE(TAG, "Missing server certificate and/or key and no SNI callback is defined");
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
if (cfg->cert_select_cb == NULL) {
ESP_LOGE(TAG, "Missing server certificate and/or key and no certificate selection callback is defined");
} else {
ESP_LOGD(TAG, "Missing server certificate and/or key, but SNI callback is defined. Callback MUST ALWAYS call mbedtls_ssl_set_hs_own_cert, or the handshake will abort!");
ESP_LOGD(TAG, "Missing server certificate and/or key, but certificate selection callback is defined. Callback MUST ALWAYS call mbedtls_ssl_set_hs_own_cert, or the handshake will abort!");
return ESP_OK;
}
#else
Expand Down Expand Up @@ -797,13 +806,6 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
return -1;
}

#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
if (cfg->sni_callback != NULL) {
ESP_LOGI(TAG, "Initializing server side SNI callback");
mbedtls_ssl_conf_sni(&tls->conf, cfg->sni_callback, cfg->sni_callback_p_info);
}
#endif

tls->read = esp_mbedtls_read;
tls->write = esp_mbedtls_write;
int ret;
Expand Down
6 changes: 3 additions & 3 deletions components/esp_https_server/include/esp_https_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ struct httpd_ssl_config {
/** User callback for esp_https_server */
esp_https_server_user_cb *user_cb;

#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
esp_tls_server_sni_callback *sni_callback; /*!< Server Name Identification callback to use */
void *sni_callback_p_info; /*!< Data to pass to the SNI callback. */
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
esp_tls_handshake_callback cert_select_cb; /*!< Certificate selection callback to use */
#endif
void *ssl_userdata; /*!< user data to add to the ssl context */
};

typedef struct httpd_ssl_config httpd_ssl_config_t;
Expand Down
72 changes: 30 additions & 42 deletions components/esp_https_server/src/https_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,22 +200,20 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
}
esp_tls_cfg_server_t *cfg = (esp_tls_cfg_server_t *)calloc(1, sizeof(esp_tls_cfg_server_t));
if (!cfg) {
free(ssl_ctx);
return NULL;
goto free_ssl_ctx;
}

if (config->session_tickets) {
if ( esp_tls_cfg_server_session_tickets_init(cfg) != ESP_OK ) {
ESP_LOGE(TAG, "Failed to init session ticket support");
free(ssl_ctx);
free(cfg);
return NULL;
goto free_cfg;
}
}

#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
cfg->sni_callback = config->sni_callback;
cfg->sni_callback_p_info = config->sni_callback_p_info;
cfg->userdata = config->ssl_userdata;

#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
cfg->cert_select_cb = config->cert_select_cb;
#endif

ssl_ctx->tls_cfg = cfg;
Expand All @@ -230,9 +228,7 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
cfg->cacert_bytes = config->cacert_len;
} else {
ESP_LOGE(TAG, "Could not allocate memory for client certificate authority");
free(cfg);
free(ssl_ctx);
return NULL;
goto free_cfg;
}
}

Expand All @@ -245,23 +241,17 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
cfg->servercert_bytes = config->servercert_len;
} else {
ESP_LOGE(TAG, "Could not allocate memory for server certificate");
free((void *) cfg->cacert_buf);
free(cfg);
free(ssl_ctx);
return NULL;
goto free_cacert;
}
} else {
#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
if (config->sni_callback == NULL) {
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
if (config->cert_select_cb == NULL) {
#endif
ESP_LOGE(TAG, "No Server certificate supplied");
free((void *) cfg->cacert_buf);
free(cfg);
free(ssl_ctx);
return NULL;
#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
goto free_cacert;
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
} else {
ESP_LOGW(TAG, "Server certificate not supplied, make sure to supply it in the SNI hook!");
ESP_LOGW(TAG, "Server certificate not supplied, make sure to supply it in the certificate selection hook!");
}
#endif
}
Expand All @@ -277,36 +267,34 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
cfg->serverkey_bytes = config->prvtkey_len;
} else {
ESP_LOGE(TAG, "Could not allocate memory for server key");
free((void *) cfg->servercert_buf);
free((void *) cfg->cacert_buf);
free(cfg);
free(ssl_ctx);
return NULL;
goto free_servercert;
}
} else {
#if defined(CONFIG_ESP_TLS_SERVER_SNI_HOOK)
if (config->sni_callback == NULL) {
ESP_LOGE(TAG, "No Server key supplied and no SNI hook is present");
free((void *) cfg->servercert_buf);
free((void *) cfg->cacert_buf);
free(cfg);
free(ssl_ctx);
return NULL;
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
if (config->cert_select_cb == NULL) {
ESP_LOGE(TAG, "No Server key supplied and no certificate selection hook is present");
goto free_servercert;
} else {
ESP_LOGW(TAG, "Server key not supplied, make sure to supply it in the SNI hook");
ESP_LOGW(TAG, "Server key not supplied, make sure to supply it in the certificate selection hook");
}
#else
ESP_LOGE(TAG, "No Server key supplied");
free((void *) cfg->servercert_buf);
free((void *) cfg->cacert_buf);
free(cfg);
free(ssl_ctx);
return NULL;
goto free_servercert;
#endif
}
}

return ssl_ctx;

free_servercert:
free((void *) cfg->servercert_buf);
free_cacert:
free((void *) cfg->cacert_buf);
free_cfg:
free(cfg);
free_ssl_ctx:
free(ssl_ctx);
return NULL;
}

/** Start the server */
Expand Down

0 comments on commit 39a6ec0

Please sign in to comment.