From 46643ab40f586dd93e10ece211953d3e41ccf2a2 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 11 Mar 2020 17:18:27 +0530 Subject: [PATCH] esp_tls_wolfssl: Add support for PSK using wolfSSL, enable SNI and ALPN --- components/esp-tls/Kconfig | 14 +-- components/esp-tls/esp_tls_wolfssl.c | 140 ++++++++++++++++++++------- 2 files changed, 110 insertions(+), 44 deletions(-) diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig index e13455984..2ae7a0727 100644 --- a/components/esp-tls/Kconfig +++ b/components/esp-tls/Kconfig @@ -22,15 +22,15 @@ menu "ESP-TLS" config ESP_TLS_PSK_VERIFICATION bool "Enable PSK verification" - depends on ESP_TLS_USING_MBEDTLS - select MBEDTLS_PSK_MODES - select MBEDTLS_KEY_EXCHANGE_PSK - select MBEDTLS_KEY_EXCHANGE_DHE_PSK - select MBEDTLS_KEY_EXCHANGE_ECDHE_PSK - select MBEDTLS_KEY_EXCHANGE_RSA_PSK + select MBEDTLS_PSK_MODES if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_PSK if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_DHE_PSK if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_ECDHE_PSK if ESP_TLS_USING_MBEDTLS + select MBEDTLS_KEY_EXCHANGE_RSA_PSK if ESP_TLS_USING_MBEDTLS default n help - Enable support for pre shared key ciphers, uses the mbedtls crypto library + Enable support for pre shared key ciphers, supported for both mbedTLS as well as + wolfSSL TLS library. config ESP_WOLFSSL_SMALL_CERT_VERIFY bool "Enable SMALL_CERT_VERIFY" diff --git a/components/esp-tls/esp_tls_wolfssl.c b/components/esp-tls/esp_tls_wolfssl.c index 6433614a7..e351828bc 100644 --- a/components/esp-tls/esp_tls_wolfssl.c +++ b/components/esp-tls/esp_tls_wolfssl.c @@ -34,6 +34,22 @@ static const char *TAG = "esp-tls-wolfssl"; /* Prototypes for the static functions */ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls); +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) +static inline unsigned int esp_wolfssl_psk_client_cb(WOLFSSL* ssl, const char* hint, char* identity, + unsigned int id_max_len, unsigned char* key,unsigned int key_max_len); +static esp_err_t esp_wolfssl_set_cipher_list(WOLFSSL_CTX *ctx); +#ifdef WOLFSSL_TLS13 +#define PSK_MAX_ID_LEN 128 +#else +#define PSK_MAX_ID_LEN 64 +#endif +#define PSK_MAX_KEY_LEN 64 + +static char psk_id_str[PSK_MAX_ID_LEN]; +static uint8_t psk_key_array[PSK_MAX_KEY_LEN]; +static uint8_t psk_key_max_len = 0; +#endif /* CONFIG_ESP_TLS_PSK_VERIFICATION */ + #ifdef CONFIG_ESP_TLS_SERVER static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls); #endif /* CONFIG_ESP_TLS_SERVER */ @@ -139,22 +155,6 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; } - if (cfg->alpn_protos) { -#ifdef CONFIG_WOLFSSL_HAVE_ALPN - char **alpn_list = (char **)cfg->alpn_protos; - for (; *alpn_list != NULL; alpn_list ++) { - if ((ret = wolfSSL_UseALPN( (WOLFSSL *)tls->priv_ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)) != WOLFSSL_SUCCESS) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); - ESP_LOGE(TAG, "Use wolfSSL ALPN failed"); - return ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED; - } - } -#else - ESP_LOGE(TAG, "CONFIG_WOLFSSL_HAVE_ALPN not enabled in menuconfig"); - return ESP_FAIL; -#endif /* CONFIG_WOLFSSL_HAVE_ALPN */ - } - if (cfg->use_global_ca_store == true) { if ((esp_load_wolfssl_verify_buffer(tls, global_cacert, global_cacert_pem_bytes, FILE_TYPE_CA_CERT, &ret)) != ESP_OK) { ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); @@ -168,8 +168,31 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls } wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_PEER, NULL); } else if (cfg->psk_hint_key) { - ESP_LOGE(TAG,"psk_hint_key not supported in wolfssl"); - return ESP_FAIL; +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) + /*** PSK encryption mode is configured only if no certificate supplied and psk pointer not null ***/ + if(cfg->psk_hint_key->key == NULL || cfg->psk_hint_key->hint == NULL || cfg->psk_hint_key->key_size <= 0) { + ESP_LOGE(TAG, "Please provide appropriate key, keysize and hint to use PSK"); + return ESP_FAIL; + } + ESP_LOGI(TAG, "setting psk configurations"); + if((cfg->psk_hint_key->key_size > PSK_MAX_KEY_LEN) || (strlen(cfg->psk_hint_key->hint) > PSK_MAX_ID_LEN)) { + ESP_LOGE(TAG, "psk key length should be <= %d and identity hint length should be <= %d", PSK_MAX_KEY_LEN, PSK_MAX_ID_LEN); + return ESP_ERR_INVALID_ARG; + } + psk_key_max_len = cfg->psk_hint_key->key_size; + memset(psk_key_array, 0, sizeof(psk_key_array)); + memset(psk_id_str, 0, sizeof(psk_id_str)); + memcpy(psk_key_array, cfg->psk_hint_key->key, psk_key_max_len); + memcpy(psk_id_str, cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint)); + wolfSSL_CTX_set_psk_client_callback( (WOLFSSL_CTX *)tls->priv_ctx, esp_wolfssl_psk_client_cb); + if(esp_wolfssl_set_cipher_list( (WOLFSSL_CTX *)tls->priv_ctx) != ESP_OK) { + ESP_LOGE(TAG, "error in setting cipher-list"); + return ESP_FAIL; + } +#else + ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option"); + return ESP_ERR_INVALID_STATE; +#endif } else { wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_NONE, NULL); } @@ -200,7 +223,6 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; } -#ifdef HAVE_SNI if (!cfg->skip_common_name) { char *use_host = NULL; if (cfg->common_name != NULL) { @@ -220,7 +242,24 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls } free(use_host); } -#endif + + if (cfg->alpn_protos) { +#ifdef CONFIG_WOLFSSL_HAVE_ALPN + char **alpn_list = (char **)cfg->alpn_protos; + for (; *alpn_list != NULL; alpn_list ++) { + ESP_LOGD(TAG, "alpn protocol is %s", *alpn_list); + if ((ret = wolfSSL_UseALPN( (WOLFSSL *)tls->priv_ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)) != WOLFSSL_SUCCESS) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "wolfSSL UseALPN failed, returned %d", ret); + return ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED; + } + } +#else + ESP_LOGE(TAG, "CONFIG_WOLFSSL_HAVE_ALPN not enabled in menuconfig"); + return ESP_FAIL; +#endif /* CONFIG_WOLFSSL_HAVE_ALPN */ + } + wolfSSL_set_fd((WOLFSSL *)tls->priv_ssl, tls->sockfd); return ESP_OK; } @@ -235,22 +274,6 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; } - if (cfg->alpn_protos) { -#ifdef CONFIG_WOLFSSL_HAVE_ALPN - char **alpn_list = (char **)cfg->alpn_protos; - for (; *alpn_list != NULL; alpn_list ++) { - if ((ret = wolfSSL_UseALPN( (WOLFSSL *)tls->priv_ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "Use wolfSSL ALPN failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); - return ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED; - } - } -#else - ESP_LOGE(TAG, "CONFIG_WOLFSSL_HAVE_ALPN not enabled in menuconfig"); - return ESP_FAIL; -#endif /* CONFIG_WOLFSSL_HAVE_ALPN */ - } - if (cfg->cacert_buf != NULL) { if ((esp_load_wolfssl_verify_buffer(tls,cfg->cacert_buf, cfg->cacert_bytes, FILE_TYPE_CA_CERT, &ret)) != ESP_OK) { ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); @@ -351,7 +374,7 @@ void esp_wolfssl_verify_certificate(esp_tls_t *tls) { int flags; if ((flags = wolfSSL_get_verify_result( (WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "Failed to verify peer certificate %d!", flags); + ESP_LOGE(TAG, "Failed to verify peer certificate , returned %d!", flags); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL_CERT_FLAGS, flags); } else { ESP_LOGI(TAG, "Certificate verified."); @@ -465,3 +488,46 @@ void esp_wolfssl_free_global_ca_store(void) global_cacert_pem_bytes = 0; } } + +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) +static esp_err_t esp_wolfssl_set_cipher_list(WOLFSSL_CTX *ctx) +{ + const char *defaultCipherList; + int ret; +#if defined(HAVE_AESGCM) && !defined(NO_DH) +#ifdef WOLFSSL_TLS13 + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256:" + "TLS13-AES128-GCM-SHA256"; +#else + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; +#endif +#elif defined(HAVE_NULL_CIPHER) + defaultCipherList = "PSK-NULL-SHA256"; +#else + defaultCipherList = "PSK-AES128-CBC-SHA256"; +#endif + ESP_LOGD(TAG, "cipher list is %s", defaultCipherList); + if ((ret = wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList)) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); + ESP_LOGE(TAG, "can't set cipher list, returned %02x", ret); + return ESP_FAIL; + } + return ESP_OK; +} + +/* Some callback functions required by PSK */ +static inline unsigned int esp_wolfssl_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + memcpy(identity, psk_id_str, id_max_len); + for(int count = 0; count < psk_key_max_len; count ++) { + key[count] = psk_key_array[count]; + } + return psk_key_max_len; + /* return length of key in octets or 0 or for error */ +} +#endif /* CONFIG_ESP_TLS_PSK_VERIFICATION */