Merge branch 'feature/eap_tls_v1.3_support' into 'master'

wpa_supplicant: Add TLS v1.3 support in WiFi Enterprise Authentication

Closes WIFI-6135

See merge request espressif/esp-idf!24975
This commit is contained in:
Jiang Jiang Jian 2024-03-21 21:10:38 +08:00
commit 9971413b60
21 changed files with 778 additions and 258 deletions

View File

@ -627,3 +627,4 @@ mainmenu "Espressif IoT Development Framework Configuration"
- CONFIG_SPIRAM_SPEED_120M && CONFIG_SPIRAM_MODE_OCT
- CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
- CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL
- CONFIG_ESP_WIFI_EAP_TLS1_3

View File

@ -493,6 +493,20 @@ menu "Wi-Fi"
TLS-v1.0, TLS-v1.1 versions. Incase your server is using one of these version,
it is advisable to update your server.
Please disable this option for compatibilty with older TLS versions.
config ESP_WIFI_EAP_TLS1_3
bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection"
default n
select MBEDTLS_SSL_PROTO_TLS1_3
depends on ESP_WIFI_MBEDTLS_TLS_CLIENT && IDF_EXPERIMENTAL_FEATURES
help
Select this option to support EAP with TLS v1.3.
This configuration still supports compatibility with EAP-TLS v1.2.
Please note that enabling this configuration will cause every application which
uses TLS go for TLS1.3 if server supports that. TLS1.3 is still in development in mbedtls
and there may be interoperability issues with this. Please modify your application to set
max version as TLS1.2 if you want to enable TLS1.3 only for WiFi connection.
endif
config ESP_WIFI_WAPI_PSK
@ -629,6 +643,11 @@ menu "Wi-Fi"
disabling this will reduce binary size.
disabling this will disable the use of any esp_wifi_sta_wpa2_ent_* (as APIs will be meaningless)
Note that when using bigger certificates on low-power chips without crypto
hardware acceleration, it is recommended to adjust the task watchdog timer (TWDT)
if it is enabled. For precise information on timing requirements, you can check
performance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers.
config ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER
bool "Free dynamic buffers during WiFi enterprise connection"
depends on ESP_WIFI_ENTERPRISE_SUPPORT

View File

@ -304,6 +304,9 @@ endif()
if(CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_OWE_STA)
endif()
if(CONFIG_ESP_WIFI_EAP_TLS1_3)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TLSV13)
endif()
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -37,10 +37,21 @@
#include "mbedtls/platform.h"
#include "eap_peer/eap.h"
#ifdef CONFIG_TLSV13
#include "psa/crypto.h"
#include "md_psa.h"
#include "ssl_tls13_keys.h"
#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
psa_to_ssl_errors, \
psa_generic_status_to_mbedtls)
#endif /* CONFIG_TLSV13 */
#define TLS_RANDOM_LEN 32
#define TLS_HASH_MAX_SIZE 64
#define TLS_MASTER_SECRET_LEN 48
#define MAX_CIPHERSUITE 32
#define MAX_EXPORTER_CONTEXT_LEN 65535
@ -82,8 +93,10 @@ struct tls_connection {
struct tls_data tls_io_data;
unsigned char master_secret[TLS_MASTER_SECRET_LEN];
unsigned char randbytes[2 * TLS_RANDOM_LEN];
mbedtls_tls_prf_types tls_prf_type;
mbedtls_md_type_t mac;
mbedtls_tls_prf_types tls_prf_type;
#ifdef CONFIG_TLSV13
unsigned char exporter_master_secret[TLS_HASH_MAX_SIZE];
#endif /* CONFIG_TLSV13 */
};
static void tls_mbedtls_cleanup(tls_context_t *tls)
@ -201,6 +214,43 @@ static int set_ca_cert(tls_context_t *tls, const unsigned char *cacert, size_t c
#ifdef CONFIG_SUITEB192
static uint16_t tls_sig_algs_for_suiteb[] = {
#ifdef CONFIG_TLSV13
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA384) && \
defined(PSA_WANT_ECC_SECP_R1_384)
MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA512) && \
defined(PSA_WANT_ECC_SECP_R1_521)
MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512)
#endif
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
defined(MBEDTLS_MD_CAN_SHA512)
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
#endif \
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA512 */
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
defined(MBEDTLS_MD_CAN_SHA384)
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
#endif \
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512)
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384)
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */
#endif /* CONFIG_TLSV13 */
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_ECDSA_C)
MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG( MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512 ),
@ -235,6 +285,60 @@ static void tls_set_suiteb_config(tls_context_t *tls)
#endif
static uint16_t tls_sig_algs_for_eap[] = {
#ifdef CONFIG_TLSV13
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA256) && \
defined(PSA_WANT_ECC_SECP_R1_256)
MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256)
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA384) && \
defined(PSA_WANT_ECC_SECP_R1_384)
MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA512) && \
defined(PSA_WANT_ECC_SECP_R1_521)
MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512)
#endif
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
defined(MBEDTLS_MD_CAN_SHA512)
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
#endif \
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA512 */
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
defined(MBEDTLS_MD_CAN_SHA384)
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
#endif \
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
defined(MBEDTLS_MD_CAN_SHA256)
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
#endif \
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA256 */
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512)
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384)
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256)
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */
#endif /* CONFIG_TLSV13 */
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_ECDSA_C)
MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG( MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512 ),
@ -300,123 +404,12 @@ static int tls_disable_key_usages(void *data, mbedtls_x509_crt *cert, int depth,
}
#endif /*CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK*/
static const int eap_ciphersuite_preference[] =
{
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
#endif
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
#endif
/* The PSK suites */
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
#endif
#endif
0
};
#ifdef CONFIG_SUITEB192
static const int suiteb_rsa_ciphersuite_preference[] =
{
#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
@ -428,6 +421,9 @@ static const int suiteb_rsa_ciphersuite_preference[] =
static const int suiteb_ecc_ciphersuite_preference[] =
{
#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
@ -437,6 +433,9 @@ static const int suiteb_ecc_ciphersuite_preference[] =
};
static const int suiteb_ciphersuite_preference[] =
{
#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
@ -469,12 +468,12 @@ static void tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_con
}
} else
#endif
/* Set cipher suites if User has explicitly set those
* TODO: public API to set EAP ciphers */
if (tls->ciphersuite[0]) {
mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite);
} else if (mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 ||
(tls->cacert_ptr && mbedtls_pk_get_bitlen(&tls->cacert_ptr->pk) > 2048)) {
mbedtls_ssl_conf_ciphersuites(&tls->conf, eap_ciphersuite_preference);
}
}
static int set_client_config(const struct tls_connection_params *cfg, tls_context_t *tls)
@ -548,6 +547,22 @@ static int set_client_config(const struct tls_connection_params *cfg, tls_contex
return 0;
}
#ifdef CONFIG_TLSV13
static void tls13_extract_exporter_master_secret(struct tls_connection *conn)
{
mbedtls_ssl_context *ssl = &conn->tls->ssl;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info;
psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ciphersuite_info->mac);
size_t hash_len = PSA_HASH_LENGTH(hash_alg);
assert(hash_len != 0);
mbedtls_ssl_tls13_application_secrets *app_secrets =
&ssl->session_negotiate->app_secrets;
os_memcpy(conn->exporter_master_secret, app_secrets->exporter_master_secret, hash_len);
}
#endif /* CONFIG_TLSV13 */
static void tls_key_derivation(void *ctx,
mbedtls_ssl_key_export_type secret_type,
const unsigned char *secret,
@ -562,6 +577,12 @@ static void tls_key_derivation(void *ctx,
os_memcpy(conn->randbytes, client_random, TLS_RANDOM_LEN);
os_memcpy(conn->randbytes + 32, server_random, TLS_RANDOM_LEN);
conn->tls_prf_type = tls_prf_type;
#ifdef CONFIG_TLSV13
if (secret_type == MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET) {
tls13_extract_exporter_master_secret(conn);
}
#endif /* CONFIG_TLSV13 */
}
static int tls_create_mbedtls_handle(struct tls_connection *conn,
@ -593,6 +614,12 @@ static int tls_create_mbedtls_handle(struct tls_connection *conn,
mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg);
#if defined(CONFIG_MBEDTLS_SSL_PROTO_TLS1_3) && !defined(CONFIG_TLSV13)
/* Disable TLSv1.3 even when enabled in MbedTLS and not enabled in WiFi config.
* TODO: Remove Kconfig option for TLSv1.3 when it is matured enough */
mbedtls_ssl_conf_max_tls_version(&tls->conf, MBEDTLS_SSL_VERSION_TLS1_2);
#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 && !CONFIG_TLSV13 */
ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf);
if (ret != 0) {
wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret);
@ -633,6 +660,13 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
wpa_printf(MSG_ERROR, "TLS: Failed to allocate connection memory");
return NULL;
}
#ifdef CONFIG_TLSV13
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
wpa_printf(MSG_ERROR, "Failed to initialize PSA crypto, returned %d", (int) status);
return NULL;
}
#endif /* CONFIG_TLSV13 */
return conn;
}
@ -738,7 +772,6 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
tls_context_t *tls = conn->tls;
int ret = 0;
struct wpabuf *resp;
int cli_state;
/* data freed by sender */
conn->tls_io_data.out_data = NULL;
@ -748,17 +781,10 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
/* Multiple reads */
while (!mbedtls_ssl_is_handshake_over(&tls->ssl)) {
cli_state = tls->ssl.MBEDTLS_PRIVATE(state);
if (cli_state == MBEDTLS_SSL_CLIENT_CERTIFICATE) {
/* Read random data before session completes, not present after handshake */
if (tls->ssl.MBEDTLS_PRIVATE(handshake)) {
os_memcpy(conn->randbytes, tls->ssl.MBEDTLS_PRIVATE(handshake)->randbytes,
TLS_RANDOM_LEN * 2);
conn->mac = tls->ssl.MBEDTLS_PRIVATE(handshake)->ciphersuite_info->mac;
}
}
#ifdef CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER
int cli_state = tls->ssl.MBEDTLS_PRIVATE(state);
#endif /* CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER */
ret = mbedtls_ssl_handshake_step(&tls->ssl);
if (ret < 0) {
break;
}
@ -782,7 +808,28 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
if (!conn->tls_io_data.out_data) {
wpa_printf(MSG_INFO, "application data is null, adding one byte for ack");
u8 *dummy = os_zalloc(1);
if (dummy == NULL) {
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
goto end;
}
#ifdef CONFIG_TLSV13
if (mbedtls_ssl_get_version_number(&conn->tls->ssl) == MBEDTLS_SSL_VERSION_TLS1_3) {
*appl_data = wpabuf_alloc_ext_data(dummy, 1);
if (appl_data == NULL) {
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
os_free(dummy);
goto end;
}
return NULL;
}
#endif /* CONFIG_TLSV13 */
conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0);
if (conn->tls_io_data.out_data == NULL) {
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
os_free(dummy);
goto end;
}
}
end:
@ -997,13 +1044,24 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
}
static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
const char *label, const u8 *context,
size_t context_len, int server_random_first,
u8 *out, size_t out_len)
{
int ret;
u8 seed[2 * TLS_RANDOM_LEN];
u8 *seed, *pos;
size_t seed_len = 2 * TLS_RANDOM_LEN;
mbedtls_ssl_context *ssl = &conn->tls->ssl;
if (context_len > MAX_EXPORTER_CONTEXT_LEN) {
return -1;
}
if (context) {
// The magic value 2 represents the memory required to store the context length.
seed_len += 2 + context_len;
}
if (!ssl) {
wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__);
return -1;
@ -1013,6 +1071,11 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
return -1;
}
seed = os_malloc(seed_len);
if (!seed) {
return -1;
}
if (server_random_first) {
os_memcpy(seed, conn->randbytes + TLS_RANDOM_LEN, TLS_RANDOM_LEN);
os_memcpy(seed + TLS_RANDOM_LEN, conn->randbytes, TLS_RANDOM_LEN);
@ -1020,25 +1083,96 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN);
}
if (context) {
pos = seed + 2 * TLS_RANDOM_LEN;
WPA_PUT_BE16(pos, context_len);
pos += 2;
os_memcpy(pos, context, context_len);
}
wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN);
ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, conn->master_secret, TLS_MASTER_SECRET_LEN,
label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
label, seed, seed_len, out, out_len);
os_free(seed);
if (ret < 0) {
wpa_printf(MSG_ERROR, "prf failed, ret=%d", ret);
return -1;
}
wpa_hexdump_key(MSG_MSGDUMP, "key", out, out_len);
return ret;
}
#ifdef CONFIG_TLSV13
/* RFC 8446 Section 7.5 */
static int tls13_connection_export_key(void *tls_ctx, struct tls_connection *conn,
const char *label, const u8 *context,
size_t context_len, u8 *out, size_t out_len)
{
int ret;
mbedtls_ssl_context *ssl = &conn->tls->ssl;
psa_algorithm_t hash_alg;
size_t hash_len;
unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 };
unsigned char hashed_context[PSA_HASH_MAX_SIZE] = { 0 };
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info;
hash_alg = mbedtls_md_psa_alg_from_type(ciphersuite_info->mac);
hash_len = PSA_HASH_LENGTH(hash_alg);
ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
conn->exporter_master_secret, hash_len,
(unsigned char const *) label, (size_t) strlen(label),
NULL, 0,
MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
tmp_secret, hash_len);
if (ret != 0) {
wpa_printf(MSG_ERROR, "%s(): mbedtls_ssl_tls13_derive_secret() failed",
__func__);
return ret;
}
status = psa_hash_compute(hash_alg, context, context_len, hashed_context,
PSA_HASH_LENGTH(hash_alg), &context_len);
if (status != PSA_SUCCESS) {
wpa_printf(MSG_ERROR, "%s(): psa_hash_compute() failed",
__func__);
ret = PSA_TO_MBEDTLS_ERR(status);
return ret;
}
ret = mbedtls_ssl_tls13_hkdf_expand_label(hash_alg,
tmp_secret, hash_len,
MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exporter),
hashed_context, context_len,
out, out_len);
if (ret != 0) {
wpa_printf(MSG_ERROR, "%s(): psa_hash_compute() failed",
__func__);
return ret;
}
return 0;
}
#endif /* CONFIG_TLSV13 */
int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
const char *label, const u8 *context,
size_t context_len, u8 *out, size_t out_len)
{
return tls_connection_prf(tls_ctx, conn, label, 0, out, out_len);
#ifdef CONFIG_TLSV13
if (mbedtls_ssl_get_version_number(&conn->tls->ssl) == MBEDTLS_SSL_VERSION_TLS1_3)
return tls13_connection_export_key(tls_ctx, conn, label, context, context_len,
out, out_len);
#endif /* CONFIG_TLSV13 */
return tls_connection_prf(tls_ctx, conn, label, context, context_len,
0, out, out_len);
}
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,

View File

@ -369,6 +369,7 @@ enum wpa_ctrl_req_type {
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
WPA_CTRL_REQ_PSK_PASSPHRASE,
WPA_CTRL_REQ_EXT_CERT_CHECK,
NUM_WPA_CTRL_REQS
};

View File

@ -356,7 +356,9 @@ int __must_check tls_global_set_verify(void *tls_ctx, int check_crl,
* tls_connection_set_verify - Set certificate verification options
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @verify_peer: 1 = verify peer certificate
* @verify_peer: 0 = do not verify peer certificate, 1 = verify peer
* certificate (require it to be provided), 2 = verify peer certificate if
* provided
* @flags: Connection flags (TLS_CONN_*)
* @session_ctx: Session caching context or %NULL to use default
* @session_ctx_len: Length of @session_ctx in bytes.

View File

@ -281,13 +281,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
params->dh_blob_len)) {
wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
tlsv1_cred_free(cred);
return -1;
}
if (tlsv1_client_set_cred(conn->client, cred) < 0) {
tlsv1_cred_free(cred);
return -1;
@ -791,6 +784,7 @@ int tls_get_library_version(char *buf, size_t buf_len)
void tls_connection_set_success_data(struct tls_connection *conn,
struct wpabuf *data)
{
wpabuf_free(data);
}

View File

@ -71,6 +71,8 @@ int (*esp_crt_bundle_attach_fn)(void *conf);
void eap_peer_config_deinit(struct eap_sm *sm);
void eap_peer_blob_deinit(struct eap_sm *sm);
void eap_deinit_prev_method(struct eap_sm *sm, const char *txt);
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
const char *msg, size_t msglen);
#ifdef EAP_PEER_METHOD
static struct eap_method *eap_methods = NULL;
@ -314,6 +316,15 @@ int eap_peer_register_methods(void)
return ret;
}
static void eap_sm_free_key(struct eap_sm *sm)
{
if (sm->eapKeyData) {
bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
sm->eapKeyData = NULL;
}
}
void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
{
if (sm->m == NULL || sm->eap_method_priv == NULL)
@ -713,10 +724,10 @@ _out:
return ret;
}
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
const char *msg, size_t msglen)
{
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
struct eap_peer_config *config;
if (sm == NULL)
@ -741,14 +752,14 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
case WPA_CTRL_REQ_EAP_PASSPHRASE:
config->pending_req_passphrase++;
break;
case WPA_CTRL_REQ_EXT_CERT_CHECK:
break;
default:
return;
}
}
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
}
const char * eap_sm_get_method_name(struct eap_sm *sm)
{
@ -824,6 +835,7 @@ void eap_sm_abort(struct eap_sm *sm)
{
wpabuf_free(sm->lastRespData);
sm->lastRespData = NULL;
eap_sm_free_key(sm);
}
/**

View File

@ -249,8 +249,8 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv)
os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
os_memset(data->emsk, 0, EAP_EMSK_LEN);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
wpabuf_free(data->pending_resp);
wpabuf_clear_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_resp);
os_free(data);
}
@ -800,7 +800,7 @@ static struct wpabuf * eap_fast_process_crypto_binding(
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
data->phase2_success = 0;
wpabuf_free(resp);
wpabuf_clear_free(resp);
return NULL;
}
@ -814,7 +814,7 @@ static struct wpabuf * eap_fast_process_crypto_binding(
} else {
wpa_printf(MSG_ERROR, "EAP-FAST: Failed to derive "
"Session-Id");
wpabuf_free(resp);
wpabuf_clear_free(resp);
return NULL;
}
}
@ -1135,7 +1135,7 @@ static int eap_fast_encrypt_response(struct eap_sm *sm,
wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 "
"frame");
}
wpabuf_free(resp);
wpabuf_clear_free(resp);
return 0;
}
@ -1313,14 +1313,14 @@ continue_req:
wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 "
"TLV frame (len=%lu)",
(unsigned long) wpabuf_len(in_decrypted));
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return -1;
}
res = eap_fast_process_decrypted(sm, data, ret, identifier,
in_decrypted, out_data);
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return res;
}
@ -1598,7 +1598,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
if (sm->waiting_ext_cert_check) {
wpa_printf(MSG_DEBUG,
"EAP-FAST: Waiting external server certificate validation");
wpabuf_free(data->pending_resp);
wpabuf_clear_free(data->pending_resp);
data->pending_resp = resp;
return NULL;
}
@ -1627,7 +1627,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
"EAP-FAST: Could not derive keys");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
wpabuf_free(resp);
wpabuf_clear_free(resp);
return NULL;
}
}
@ -1636,7 +1636,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
/*
* Application data included in the handshake message.
*/
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = resp;
resp = NULL;
res = eap_fast_decrypt(sm, data, ret, id, &msg, &resp);
@ -1644,7 +1644,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
}
if (res == 1) {
wpabuf_free(resp);
wpabuf_clear_free(resp);
return eap_peer_tls_build_ack(id, EAP_TYPE_FAST,
data->fast_version);
}
@ -1670,9 +1670,9 @@ static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv)
data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
os_free(data->key_block_p);
data->key_block_p = NULL;
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
wpabuf_free(data->pending_resp);
wpabuf_clear_free(data->pending_resp);
data->pending_resp = NULL;
}

View File

@ -87,7 +87,7 @@ eap_mschapv2_deinit(struct eap_sm *sm, void *priv)
os_free(data->peer_challenge);
os_free(data->auth_challenge);
wpabuf_free(data->prev_challenge);
os_free(data);
bin_clear_free(data, sizeof(*data));
}
static void *
@ -285,7 +285,7 @@ eap_mschapv2_password_changed(struct eap_sm *sm,
WPA_EVENT_PASSWORD_CHANGED
"EAP-MSCHAPV2: Password changed successfully");
data->prev_error = 0;
os_free(config->password);
bin_clear_free(config->password, config->password_len);
if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
/* TODO: update external storage */
} else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
@ -296,7 +296,8 @@ eap_mschapv2_password_changed(struct eap_sm *sm,
config->new_password_len,
config->password);
}
os_free(config->new_password);
bin_clear_free(config->new_password,
config->new_password_len);
} else {
config->password = config->new_password;
config->password_len = config->new_password_len;

View File

@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -59,6 +59,7 @@ struct eap_peap_data {
size_t id_len;
struct wpabuf *pending_phase2_req;
struct wpabuf *pending_resp;
enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
int crypto_binding_used;
u8 binding_nonce[32];
@ -70,6 +71,15 @@ struct eap_peap_data {
};
static void eap_peap_free_key(struct eap_peap_data *data)
{
if (data->key_data) {
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
data->key_data = NULL;
}
}
static int
eap_peap_parse_phase1(struct eap_peap_data *data,
const char *phase1)
@ -197,10 +207,11 @@ eap_peap_deinit(struct eap_sm *sm, void *priv)
data->phase2_method->deinit(sm, data->phase2_priv);
os_free(data->phase2_types);
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
eap_peap_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
os_free(data);
wpabuf_clear_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_resp);
bin_clear_free(data, sizeof(*data));
}
@ -395,7 +406,7 @@ eap_tlv_build_result(struct eap_sm *sm,
wpabuf_put_be16(msg, status); /* Status */
if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
wpabuf_free(msg);
wpabuf_clear_free(msg);
return NULL;
}
@ -710,10 +721,11 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
if (*resp == NULL) {
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
wpabuf_clear_free(buf);
return -1;
}
wpabuf_put_buf(*resp, buf);
wpabuf_free(buf);
wpabuf_clear_free(buf);
break;
}
}
@ -784,7 +796,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
if (*resp == NULL) {
wpa_printf(MSG_ERROR, "phase 2 response failure");
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
}
/*
@ -849,6 +861,10 @@ eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
if (res)
return res;
if (wpabuf_len(in_decrypted) == 0) {
wpabuf_free(in_decrypted);
return 1;
}
continue_req:
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
@ -872,7 +888,7 @@ continue_req:
struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
wpabuf_len(in_decrypted));
if (nmsg == NULL) {
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return 0;
}
nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
@ -882,7 +898,7 @@ continue_req:
nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
wpabuf_len(in_decrypted));
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
in_decrypted = nmsg;
}
@ -934,7 +950,7 @@ continue_req:
wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
"EAP frame (len=%lu)",
(unsigned long) wpabuf_len(in_decrypted));
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return 0;
}
len = be_to_host16(hdr->length);
@ -943,7 +959,7 @@ continue_req:
"Phase 2 EAP frame (len=%lu hdr->length=%lu)",
(unsigned long) wpabuf_len(in_decrypted),
(unsigned long) len);
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return 0;
}
if (len < wpabuf_len(in_decrypted)) {
@ -960,7 +976,7 @@ continue_req:
case EAP_CODE_REQUEST:
if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
&resp)) {
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
wpa_printf(MSG_ERROR, "EAP-PEAP: Phase2 Request "
"processing failed");
return 0;
@ -979,7 +995,7 @@ continue_req:
"completed successfully");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return 0;
}
wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
@ -989,7 +1005,7 @@ continue_req:
ret->methodState = METHOD_DONE;
data->phase2_success = 1;
if (data->peap_outer_success == 2) {
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
"to finish authentication");
return 1;
@ -1035,7 +1051,7 @@ continue_req:
break;
}
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
if (resp) {
int skip_change2 = 0;
@ -1067,7 +1083,7 @@ continue_req:
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
"a Phase 2 frame");
}
wpabuf_free(resp);
wpabuf_clear_free(resp);
}
return 0;
@ -1122,6 +1138,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
wpabuf_set(&msg, pos, left);
res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
} else {
if (sm->waiting_ext_cert_check && data->pending_resp) {
struct eap_peer_config *config = eap_get_config(sm);
if (config->pending_ext_cert_check ==
EXT_CERT_CHECK_GOOD) {
wpa_printf(MSG_DEBUG,
"EAP-PEAP: External certificate check succeeded - continue handshake");
resp = data->pending_resp;
data->pending_resp = NULL;
sm->waiting_ext_cert_check = 0;
return resp;
}
if (config->pending_ext_cert_check ==
EXT_CERT_CHECK_BAD) {
wpa_printf(MSG_DEBUG,
"EAP-PEAP: External certificate check failed - force authentication failure");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
sm->waiting_ext_cert_check = 0;
return NULL;
}
wpa_printf(MSG_DEBUG,
"EAP-PEAP: Continuing to wait external server certificate validation");
return NULL;
}
res = eap_peer_tls_process_helper(sm, &data->ssl,
EAP_TYPE_PEAP,
data->peap_version, id, pos,
@ -1135,31 +1179,61 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
return resp;
}
if (sm->waiting_ext_cert_check) {
wpa_printf(MSG_DEBUG,
"EAP-PEAP: Waiting external server certificate validation");
wpabuf_clear_free(data->pending_resp);
data->pending_resp = resp;
return NULL;
}
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
char label[24] = {0};
const char *label;
const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
const u8 *context = NULL;
size_t context_len = 0;
wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2");
os_free(data->key_data);
eap_peap_free_key(data);
/* draft-josefsson-ppext-eap-tls-eap-05.txt
* specifies that PEAPv1 would use "client PEAP
* encryption" as the label. However, most existing
* PEAPv1 implementations seem to be using the old
* label, "client EAP encryption", instead. Use the old
* label by default, but allow it to be configured with
* phase1 parameter peaplabel=1. */
if (data->peap_version > 1 || data->force_new_label)
os_strlcpy(label, "client PEAP encryption", 24);
else
os_strlcpy(label, "client EAP encryption", 24);
* phase1 parameter peaplabel=1.
*
* When using TLS 1.3, draft-ietf-emu-tls-eap-types
* defines a new set of label and context parameters.
*/
if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
context = eap_tls13_context;
context_len = sizeof(eap_tls13_context);
} else if (data->force_new_label) {
label = "client PEAP encryption";
} else {
label = "client EAP encryption";
}
wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
"key derivation", label);
data->key_data =
eap_peer_tls_derive_key(sm, &data->ssl, label,
EAP_TLS_KEY_LEN);
context, context_len,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (data->key_data) {
wpa_hexdump_key(MSG_DEBUG,
"EAP-PEAP: Derived key",
data->key_data,
EAP_TLS_KEY_LEN);
wpa_hexdump_key(MSG_DEBUG,
"EAP-PEAP: Derived EMSK",
data->key_data +
EAP_TLS_KEY_LEN,
EAP_EMSK_LEN);
} else {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
"derive key");
@ -1206,6 +1280,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
* Application data included in the handshake message.
*/
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = resp;
resp = NULL;
wpabuf_set(&msg, pos, left);
@ -1219,7 +1294,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
}
if (res == 1) {
wpabuf_free(resp);
wpabuf_clear_free(resp);
return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
data->peap_version);
}
@ -1242,8 +1317,10 @@ static void
eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_peap_data *data = priv;
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
wpabuf_clear_free(data->pending_resp);
data->pending_resp = NULL;
data->crypto_binding_used = 0;
}
@ -1252,8 +1329,7 @@ static void *
eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_peap_data *data = priv;
os_free(data->key_data);
data->key_data = NULL;
eap_peap_free_key(data);
os_free(data->session_id);
data->session_id = NULL;
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
@ -1341,6 +1417,29 @@ eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
}
static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
u8 *key;
if (!data->key_data || !data->phase2_success)
return NULL;
if (data->crypto_binding_used) {
/* [MS-PEAP] does not define EMSK derivation */
return NULL;
}
key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
if (!key)
return NULL;
*len = EAP_EMSK_LEN;
return key;
}
static u8 *
eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
{
@ -1377,6 +1476,7 @@ eap_peer_peap_register(void)
eap->process = eap_peap_process;
eap->isKeyAvailable = eap_peap_isKeyAvailable;
eap->getKey = eap_peap_getKey;
eap->get_emsk = eap_peap_get_emsk;
eap->get_status = eap_peap_get_status;
eap->has_reauth_data = eap_peap_has_reauth_data;
eap->deinit_for_reauth = eap_peap_deinit_for_reauth;

View File

@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TLS (RFC 2716)
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
* EAP peer method: EAP-TLS (RFC 5216, RFC 9190)
* Copyright (c) 2004-2008, 2012-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -27,6 +27,8 @@ struct eap_tls_data {
size_t id_len;
void *ssl_ctx;
u8 eap_type;
struct wpabuf *pending_resp;
bool prot_success_received;
};
@ -59,14 +61,24 @@ static void * eap_tls_init(struct eap_sm *sm)
}
static void eap_tls_free_key(struct eap_tls_data *data)
{
if (data->key_data) {
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
data->key_data = NULL;
}
}
static void eap_tls_deinit(struct eap_sm *sm, void *priv)
{
struct eap_tls_data *data = priv;
if (data == NULL)
return;
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
eap_tls_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_resp);
os_free(data);
}
@ -110,14 +122,37 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
struct eap_method_ret *ret)
{
const char *label;
const u8 eap_tls13_context[] = { EAP_TYPE_TLS };
const u8 *context = NULL;
size_t context_len = 0;
wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_UNCOND_SUCC;
if (data->ssl.tls_out) {
wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining");
return;
}
os_free(data->key_data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
"client EAP encryption",
if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
context = eap_tls13_context;
context_len = 1;
/* A possible NewSessionTicket may be received before
* EAP-Success, so need to allow it to be received. */
ret->methodState = METHOD_MAY_CONT;
ret->decision = DECISION_COND_SUCC;
} else {
label = "client EAP encryption";
ret->methodState = METHOD_DONE;
ret->decision = DECISION_UNCOND_SUCC;
}
eap_tls_free_key(data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
context, context_len,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (data->key_data) {
@ -154,6 +189,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
const u8 *pos;
struct eap_tls_data *data = priv;
if (sm->waiting_ext_cert_check && data->pending_resp) {
struct eap_peer_config *config = eap_get_config(sm);
if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
wpa_printf(MSG_DEBUG,
"EAP-TLS: External certificate check succeeded - continue handshake");
resp = data->pending_resp;
data->pending_resp = NULL;
sm->waiting_ext_cert_check = 0;
return resp;
}
if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
wpa_printf(MSG_DEBUG,
"EAP-TLS: External certificate check failed - force authentication failure");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
sm->waiting_ext_cert_check = 0;
return NULL;
}
wpa_printf(MSG_DEBUG,
"EAP-TLS: Continuing to wait external server certificate validation");
return NULL;
}
pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
reqData, &left, &flags);
if (pos == NULL)
@ -174,7 +235,28 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
return eap_tls_failure(sm, data, ret, res, resp, id);
}
if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
if (sm->waiting_ext_cert_check) {
wpa_printf(MSG_DEBUG,
"EAP-TLS: Waiting external server certificate validation");
wpabuf_free(data->pending_resp);
data->pending_resp = resp;
return NULL;
}
/* RFC 9190 Section 2.5 */
if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 &&
*wpabuf_head_u8(resp) == 0) {
wpa_printf(MSG_DEBUG,
"EAP-TLS: ACKing protected success indication (appl data 0x00)");
eap_peer_tls_reset_output(&data->ssl);
res = 1;
ret->methodState = METHOD_DONE;
ret->decision = DECISION_UNCOND_SUCC;
data->prot_success_received = true;
}
if (tls_connection_established(data->ssl_ctx, data->ssl.conn) &&
(!data->ssl.tls_v13 || data->prot_success_received))
eap_tls_success(sm, data, ret);
if (res == 1) {

View File

@ -256,6 +256,8 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @data: Data for TLS processing
* @label: Label string for deriving the keys, e.g., "client EAP encryption"
* @context: Optional extra upper-layer context (max len 2^16)
* @context_len: The length of the context value
* @len: Length of the key material to generate (usually 64 for MSK)
* Returns: Pointer to allocated key on success or %NULL on failure
*
@ -264,9 +266,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
* different label to bind the key usage into the generated material.
*
* The caller is responsible for freeing the returned buffer.
*
* Note: To provide the RFC 5705 context, the context variable must be non-NULL.
*/
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len)
const char *label, const u8 *context,
size_t context_len, size_t len)
{
u8 *out;
@ -274,8 +279,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
if (out == NULL)
return NULL;
if (tls_connection_export_key(data->ssl_ctx, data->conn, label, 0, 0, out,
len)) {
if (tls_connection_export_key(data->ssl_ctx, data->conn, label,
context, context_len, out, len)) {
os_free(out);
return NULL;
}
@ -303,6 +308,30 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct tls_random keys;
u8 *out;
if (data->tls_v13) {
u8 *id, *method_id;
const u8 context[] = { eap_type };
/* Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
* Type-Code, 64)
*/
*len = 1 + 64;
id = os_malloc(*len);
if (!id)
return NULL;
method_id = eap_peer_tls_derive_key(
sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 64);
if (!method_id) {
os_free(id);
return NULL;
}
id[0] = eap_type;
os_memcpy(id + 1, method_id, 64);
os_free(method_id);
return id;
}
/*
* TLS library did not support session ID generation,
* so get the needed TLS session parameters
@ -616,6 +645,8 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
*/
int res = eap_tls_process_input(sm, data, in_data, in_len,
out_data);
char buf[20];
if (res) {
/*
* Input processing failed (res = -1) or more data is
@ -628,6 +659,12 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
* The incoming message has been reassembled and processed. The
* response was allocated into data->tls_out buffer.
*/
if (tls_get_version(data->ssl_ctx, data->conn,
buf, sizeof(buf)) == 0) {
wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf);
data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
}
}
if (data->tls_out == NULL) {

View File

@ -78,6 +78,11 @@ struct eap_ssl_data {
* client_cert_conf: Whether client certificate has been configured
*/
bool client_cert_conf;
/**
* tls_v13 - Whether TLS v1.3 or newer is used
*/
int tls_v13;
};
@ -98,7 +103,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
struct eap_peer_config *config, u8 eap_type);
void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len);
const char *label, const u8 *context,
size_t context_len, size_t len);
u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct eap_ssl_data *data, u8 eap_type,
size_t *len);

View File

@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TTLS (RFC 5281)
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -59,6 +59,7 @@ struct eap_ttls_data {
size_t id_len;
struct wpabuf *pending_phase2_req;
struct wpabuf *pending_resp;
#ifdef EAP_TNC
int ready_for_tnc;
@ -126,6 +127,15 @@ static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
}
static void eap_ttls_free_key(struct eap_ttls_data *data)
{
if (data->key_data) {
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
data->key_data = NULL;
}
}
static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
{
struct eap_ttls_data *data = priv;
@ -134,9 +144,10 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
eap_ttls_phase2_eap_deinit(sm, data);
os_free(data->phase2_eap_types);
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
eap_ttls_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_resp);
os_free(data);
}
@ -186,7 +197,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
if (msg == NULL) {
wpabuf_free(*resp);
wpabuf_clear_free(*resp);
*resp = NULL;
return -1;
}
@ -196,7 +207,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
pos += wpabuf_len(*resp);
AVP_PAD(avp, pos);
wpabuf_free(*resp);
wpabuf_clear_free(*resp);
wpabuf_put(msg, pos - avp);
*resp = msg;
return 0;
@ -206,10 +217,24 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
static int eap_ttls_v0_derive_key(struct eap_sm *sm,
struct eap_ttls_data *data)
{
os_free(data->key_data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
"ttls keying material",
EAP_TLS_KEY_LEN);
const char *label;
const u8 eap_tls13_context[1] = { EAP_TYPE_TTLS };
const u8 *context = NULL;
size_t context_len = 0;
if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
context = eap_tls13_context;
context_len = sizeof(eap_tls13_context);
} else {
label = "ttls keying material";
}
eap_ttls_free_key(data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
context, context_len,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (!data->key_data) {
wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive key");
return -1;
@ -240,17 +265,18 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
struct eap_ttls_data *data, size_t len)
{
return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge",
NULL, 0, len);
}
#endif /* CONFIG_FIPS */
static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
u8 method)
int vendor, enum eap_type method)
{
size_t i;
for (i = 0; i < data->num_phase2_eap_types; i++) {
if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
if (data->phase2_eap_types[i].vendor != vendor ||
data->phase2_eap_types[i].method != method)
continue;
@ -297,17 +323,19 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
struct eap_ttls_data *data,
struct eap_method_ret *ret,
struct eap_hdr *hdr, size_t len,
u8 method, struct wpabuf **resp)
int vendor, enum eap_type method,
struct wpabuf **resp)
{
#ifdef EAP_TNC
if (data->tnc_started && data->phase2_method &&
data->phase2_priv && method == EAP_TYPE_TNC &&
data->phase2_priv &&
vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC &&
data->phase2_eap_type.method == EAP_TYPE_TNC)
return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
resp);
if (data->ready_for_tnc && !data->tnc_started &&
method == EAP_TYPE_TNC) {
vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
"EAP method");
data->tnc_started = 1;
@ -321,7 +349,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
return -1;
}
data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
data->phase2_eap_type.vendor = vendor;
data->phase2_eap_type.method = method;
wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
"Phase 2 EAP vendor %d method %d (TNC)",
@ -335,10 +363,11 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
data->phase2_eap_type.method == EAP_TYPE_NONE)
eap_ttls_phase2_select_eap_method(data, method);
eap_ttls_phase2_select_eap_method(data, vendor, method);
if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
{
if (vendor != data->phase2_eap_type.vendor ||
method != data->phase2_eap_type.method ||
(vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE)) {
if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
data->num_phase2_eap_types,
hdr, resp))
@ -347,8 +376,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
}
if (data->phase2_priv == NULL) {
data->phase2_method = eap_peer_get_eap_method(
EAP_VENDOR_IETF, method);
data->phase2_method = eap_peer_get_eap_method(vendor, method);
if (data->phase2_method) {
sm->init_phase2 = 1;
data->phase2_priv = data->phase2_method->init(sm);
@ -356,8 +384,9 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
}
}
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
"Phase 2 EAP method %d", method);
wpa_printf(MSG_INFO,
"EAP-TTLS: failed to initialize Phase 2 EAP method %u:%u",
vendor, method);
return -1;
}
@ -386,9 +415,23 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
case EAP_TYPE_IDENTITY:
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
break;
case EAP_TYPE_EXPANDED:
if (len < sizeof(struct eap_hdr) + 8) {
wpa_printf(MSG_INFO,
"EAP-TTLS: Too short Phase 2 request (expanded header) (len=%lu)",
(unsigned long) len);
return -1;
}
if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
WPA_GET_BE24(pos + 1),
WPA_GET_BE32(pos + 4),
resp) < 0)
return -1;
break;
default:
if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
*pos, resp) < 0)
EAP_VENDOR_IETF, *pos,
resp) < 0)
return -1;
break;
}
@ -446,7 +489,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
challenge = eap_ttls_implicit_challenge(
sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
if (challenge == NULL) {
wpabuf_free(msg);
wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
"implicit challenge");
return -1;
@ -465,7 +508,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
*pos++ = 0; /* Flags */
if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
os_free(challenge);
wpabuf_free(msg);
wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
"random data for peer challenge");
return -1;
@ -479,7 +522,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
peer_challenge, pos, data->auth_response,
data->master_key)) {
os_free(challenge);
wpabuf_free(msg);
wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
"response");
return -1;
@ -551,7 +594,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
challenge = eap_ttls_implicit_challenge(
sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
if (challenge == NULL) {
wpabuf_free(msg);
wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
"implicit challenge");
return -1;
@ -571,12 +614,26 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
os_memset(pos, 0, 24); /* LM-Response */
pos += 24;
if (pwhash) {
challenge_response(challenge, password, pos); /* NT-Response */
/* NT-Response */
if (challenge_response(challenge, password, pos)) {
wpa_printf(MSG_ERROR,
"EAP-TTLS/MSCHAP: Failed derive password hash");
wpabuf_clear_free(msg);
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
password, 16);
} else {
nt_challenge_response(challenge, password, password_len,
pos); /* NT-Response */
/* NT-Response */
if (nt_challenge_response(challenge, password, password_len,
pos)) {
wpa_printf(MSG_ERROR,
"EAP-TTLS/MSCHAP: Failed derive password");
wpabuf_clear_free(msg);
return -1;
}
wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
password, password_len);
}
@ -691,7 +748,7 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
challenge = eap_ttls_implicit_challenge(
sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
if (challenge == NULL) {
wpabuf_free(msg);
wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
"implicit challenge");
return -1;
@ -999,9 +1056,10 @@ static int eap_ttls_encrypt_response(struct eap_sm *sm,
data->ttls_version, identifier,
resp, out_data)) {
wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to encrypt a Phase 2 frame");
wpabuf_clear_free(resp);
return -1;
}
wpabuf_free(resp);
wpabuf_clear_free(resp);
return 0;
}
@ -1221,7 +1279,7 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm,
config->pending_req_password ||
config->pending_req_otp ||
config->pending_req_new_password) {
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = wpabuf_dup(in_decrypted);
}
@ -1263,7 +1321,7 @@ static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
* processing when EAP request is re-processed after
* user input.
*/
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = wpabuf_alloc(0);
}
@ -1336,7 +1394,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
in_decrypted = data->pending_phase2_req;
data->pending_phase2_req = NULL;
if (wpabuf_len(in_decrypted) == 0) {
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
return eap_ttls_implicit_identity_request(
sm, data, ret, identifier, out_data);
}
@ -1345,6 +1403,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
if ((in_data == NULL || wpabuf_len(in_data) == 0) &&
data->phase2_start) {
start:
return eap_ttls_phase2_start(sm, data, ret, identifier,
out_data);
}
@ -1359,6 +1418,20 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
if (retval)
goto done;
if (wpabuf_len(in_decrypted) == 0) {
wpabuf_free(in_decrypted);
goto start;
}
/* RFC 9190 Section 2.5 */
if (data->ssl.tls_v13 && wpabuf_len(in_decrypted) == 1 &&
*wpabuf_head_u8(in_decrypted) == 0) {
wpa_printf(MSG_DEBUG,
"EAP-TLS: ACKing protected success indication (appl data 0x00)");
eap_peer_tls_reset_output(&data->ssl);
wpabuf_free(in_decrypted);
return 1;
}
continue_req:
data->phase2_start = 0;
@ -1372,7 +1445,7 @@ continue_req:
&parse, in_decrypted, out_data);
done:
wpabuf_free(in_decrypted);
wpabuf_clear_free(in_decrypted);
os_free(parse.eapdata);
if (retval < 0) {
@ -1393,10 +1466,52 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
{
int res;
if (sm->waiting_ext_cert_check && data->pending_resp) {
struct eap_peer_config *config = eap_get_config(sm);
if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
wpa_printf(MSG_DEBUG,
"EAP-TTLS: External certificate check succeeded - continue handshake");
*out_data = data->pending_resp;
data->pending_resp = NULL;
sm->waiting_ext_cert_check = 0;
return 0;
}
if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
wpa_printf(MSG_DEBUG,
"EAP-TTLS: External certificate check failed - force authentication failure");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
sm->waiting_ext_cert_check = 0;
return 0;
}
wpa_printf(MSG_DEBUG,
"EAP-TTLS: Continuing to wait external server certificate validation");
return 0;
}
res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
data->ttls_version, identifier,
in_data, in_len, out_data);
if (res < 0) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS processing failed");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
return -1;
}
if (sm->waiting_ext_cert_check) {
wpa_printf(MSG_DEBUG,
"EAP-TTLS: Waiting external server certificate validation");
wpabuf_clear_free(data->pending_resp);
data->pending_resp = *out_data;
*out_data = NULL;
return 0;
}
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
"Phase 2");
@ -1426,7 +1541,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
/*
* Application data included in the handshake message.
*/
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = *out_data;
*out_data = NULL;
wpabuf_set(&msg, in_data, in_len);
@ -1515,7 +1630,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
/* FIX: what about res == -1? Could just move all error processing into
* the other functions and get rid of this res==1 case here. */
if (res == 1) {
wpabuf_free(resp);
wpabuf_clear_free(resp);
return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
data->ttls_version);
}
@ -1535,8 +1650,10 @@ static bool eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_ttls_data *data = priv;
wpabuf_free(data->pending_phase2_req);
wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
wpabuf_clear_free(data->pending_resp);
data->pending_resp = NULL;
#ifdef EAP_TNC
data->ready_for_tnc = 0;
data->tnc_started = 0;
@ -1547,8 +1664,7 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_ttls_data *data = priv;
os_free(data->key_data);
data->key_data = NULL;
eap_ttls_free_key(data);
os_free(data->session_id);
data->session_id = NULL;
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {

View File

@ -776,7 +776,8 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
hlen = tls_key_x_server_params_hash(
conn->rl.tls_version, conn->client_random,
conn->server_random, server_params,
server_params_end - server_params, hash);
server_params_end - server_params, hash,
sizeof(hash));
}
if (hlen < 0)

View File

@ -380,7 +380,7 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
const u8 *server_random,
const u8 *server_params,
size_t server_params_len, u8 *hash)
size_t server_params_len, u8 *hash, size_t hsz)
{
u8 *hpos;
size_t hlen;
@ -395,6 +395,8 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
crypto_hash_update(ctx, server_params, server_params_len);
hlen = MD5_MAC_LEN;
if (hsz < hlen)
return -1;
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
return -1;
hpos += hlen;
@ -405,7 +407,7 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
crypto_hash_update(ctx, server_params, server_params_len);
hlen = hash + sizeof(hash) - hpos;
hlen = hsz - hlen;
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
return -1;
hpos += hlen;

View File

@ -267,7 +267,8 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_Alg,
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
const u8 *server_random,
const u8 *server_params,
size_t server_params_len, u8 *hash);
size_t server_params_len,
u8 *hash, size_t hsz);
int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
const u8 *data, size_t data_len,
const u8 *pos, size_t len, u8 *alert);

View File

@ -620,7 +620,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
hlen = tls_key_x_server_params_hash(
conn->rl.tls_version, conn->client_random,
conn->server_random, server_params,
pos - server_params, hash);
pos - server_params, hash, sizeof(hash));
}
if (hlen < 0) {

View File

@ -10,6 +10,9 @@
**WPA3 Enterprise(192 bit)**: WPA3 Enterprise + AES256 Keys(GCMP256/CCMP256) + BIP256 + RSA3096/EC certs + NSA SuiteB ciphers in EAP authentication.
*Note:*
Note that when using bigger certificates on low-power chips without crypto hardware acceleration, it is recommended to adjust the task watchdog timer (TWDT) if it is enabled. For precise information on timing requirements, you can check performance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers.
# WiFi Enterprise Example
This example shows how ESP32 connects to AP with Wi-Fi enterprise encryption. The example does the following steps:

View File

@ -57,10 +57,17 @@ static const char *TAG = "example";
To embed it in the app binary, the PEM, CRT and KEY file is named
in the component.mk COMPONENT_EMBED_TXTFILES variable.
*/
#ifdef CONFIG_EXAMPLE_VALIDATE_SERVER_CERT
#if defined(CONFIG_EXAMPLE_VALIDATE_SERVER_CERT) || \
defined(CONFIG_EXAMPLE_WPA3_ENTERPRISE) || \
defined(CONFIG_EXAMPLE_WPA3_192BIT_ENTERPRISE) || \
defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
#define SERVER_CERT_VALIDATION_ENABLED
#endif
#ifdef SERVER_CERT_VALIDATION_ENABLED
extern uint8_t ca_pem_start[] asm("_binary_ca_pem_start");
extern uint8_t ca_pem_end[] asm("_binary_ca_pem_end");
#endif /* CONFIG_EXAMPLE_VALIDATE_SERVER_CERT */
#endif /* SERVER_CERT_VALIDATION_ENABLED */
#ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS
extern uint8_t client_crt_start[] asm("_binary_client_crt_start");
@ -88,9 +95,9 @@ static void event_handler(void* arg, esp_event_base_t event_base,
static void initialise_wifi(void)
{
#ifdef CONFIG_EXAMPLE_VALIDATE_SERVER_CERT
#ifdef SERVER_CERT_VALIDATION_ENABLED
unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start;
#endif /* CONFIG_EXAMPLE_VALIDATE_SERVER_CERT */
#endif /* SERVER_CERT_VALIDATION_ENABLED */
#ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS
unsigned int client_crt_bytes = client_crt_end - client_crt_start;
@ -123,11 +130,9 @@ static void initialise_wifi(void)
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_eap_client_set_identity((uint8_t *)EXAMPLE_EAP_ID, strlen(EXAMPLE_EAP_ID)) );
#if defined(CONFIG_EXAMPLE_VALIDATE_SERVER_CERT) || \
defined(CONFIG_EXAMPLE_WPA3_ENTERPRISE) || \
defined(CONFIG_EXAMPLE_WPA3_192BIT_ENTERPRISE)
#ifdef SERVER_CERT_VALIDATION_ENABLED
ESP_ERROR_CHECK(esp_eap_client_set_ca_cert(ca_pem_start, ca_pem_bytes) );
#endif /* CONFIG_EXAMPLE_VALIDATE_SERVER_CERT */ /* EXAMPLE_WPA3_ENTERPRISE */
#endif /* SERVER_CERT_VALIDATION_ENABLED */
#ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS
ESP_ERROR_CHECK(esp_eap_client_set_certificate_and_key(client_crt_start, client_crt_bytes,